Fixing the Billing Redirect 404 in v1.0.27
Fixing the Billing Redirect 404 in v1.0.27
Release: v1.0.27
What Happened
When a user completed or cancelled a Stripe Checkout session, Stripe would redirect them back to Sidekick — but the destination URL (/dashboard/billing) didn't exist as a rendered page in the application. The result was a 404 error immediately after payment, leaving users with no confirmation that their subscription had been activated or that their checkout had been cancelled.
The Root Cause
The Stripe redirect URLs are configured in src/lib/routers/billing.ts inside the createCheckoutSession tRPC mutation:
// src/lib/routers/billing.ts (lines 60 and 76)
success_url: `${baseUrl}/dashboard/billing?success=true`,
cancel_url: `${baseUrl}/dashboard/billing?canceled=true`,
Both URLs point to /dashboard/billing. However, while the settings page at src/app/dashboard/settings/page.tsx (lines 28–37) renders a "Manage Billing" section with a portal link, no page component existed at the /dashboard/billing path — so Next.js served a 404 for every Stripe redirect.
The Fix
A new page was created at src/app/dashboard/billing/page.tsx to serve as the landing target for Stripe post-payment redirects. It handles two query parameter states:
| Query parameter | Meaning |
|---|---|
?success=true | Checkout completed successfully; subscription is active |
?canceled=true | User cancelled the Stripe Checkout flow |
The page reads these parameters and renders the appropriate UI — a success confirmation or a cancellation notice — so users always receive clear feedback after interacting with Stripe.
Impact
- Before: Every Stripe Checkout completion or cancellation landed on a 404 page.
- After: Users are redirected to
/dashboard/billingand see a contextual confirmation screen matching the outcome of their checkout session.
No Action Required
This fix is applied automatically. Existing billing configurations and Stripe webhook integrations are unaffected. The success_url and cancel_url values in the billing router remain unchanged — the missing page now simply exists to receive them.