{"record":{"id":"46775ec1b1d8b7b7","repo":"TryGhost/Ghost","slug":"latest-stripe-checkout-session-does-not-include-a-46775e","errorCode":null,"errorMessage":"Latest Stripe checkout session does not include a success URL","messagePattern":"Latest Stripe checkout session does not include a success URL","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"e2e/helpers/playwright/flows/signup.ts","lineNumber":53,"sourceCode":"    const emailAddress = opts?.emailAddress ?? `test${faker.string.uuid()}@ghost.org`;\n    const name = opts?.name ?? faker.person.fullName();\n\n    await signUpPage.waitForPortalToOpen();\n\n    if (opts?.cadence) {\n        await signUpPage.switchCadence(opts.cadence);\n    }\n\n    await signUpPage.fillAndSubmitPaidSignup(emailAddress, name, opts?.tierName);\n\n    const fakeCheckoutPage = new FakeStripeCheckoutPage(page);\n    await fakeCheckoutPage.waitUntilLoaded();\n    await stripe.completeLatestSubscriptionCheckout({name});\n\n    const latestCheckoutSession = stripe.getCheckoutSessions().at(-1);\n    const successUrl = latestCheckoutSession?.response.success_url;\n    if (!successUrl) {\n        throw new Error('Latest Stripe checkout session does not include a success URL');\n    }\n\n    await page.goto(successUrl);\n\n    return {emailAddress, name};\n}\n","sourceCodeStart":35,"sourceCodeEnd":60,"githubUrl":"https://github.com/TryGhost/Ghost/blob/47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe/e2e/helpers/playwright/flows/signup.ts#L35-L60","documentation":"Same success-URL guard as the donations/offers flows, thrown in the paid signup flow after `stripe.completeLatestSubscriptionCheckout`. After `signUpPage.fillAndSubmitPaidSignup`, the test expects the most recent Stripe checkout session to carry a `success_url` to navigate to. Absence means no subscription checkout session was recorded or its response omits the field.","triggerScenarios":"Paid signup flow submits the form and the fake checkout loads, but `getCheckoutSessions().at(-1)` is undefined or its `response.success_url` is missing.","commonSituations":"Tier/pricing not synced to Stripe before signup so no checkout session is created; cadence switch (`switchCadence`) left the signup in an invalid state; Stripe test service not capturing the subscription checkout; mock response shape regression.","solutions":["Ensure the tier named in `opts.tierName` is Stripe-synced (use the tiers sync wait flow) before paid signup.","Confirm `fakeCheckoutPage.waitUntilLoaded()` resolved and `completeLatestSubscriptionCheckout` captured a session.","Log `stripe.getCheckoutSessions().length` immediately before reading the success URL.","Validate the cadence option is one the tier supports ('monthly'|'yearly')."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const sessions = stripe.getCheckoutSessions();\nif (!sessions.length || !sessions.at(-1)?.response?.success_url) {\n    throw new Error(`Paid signup checkout not recorded (${sessions.length} sessions)`);\n}","typeGuard":"function isCheckoutSessionWithSuccessUrl(s: unknown): s is {response: {success_url: string}} {\n    return !!s && typeof (s as any).response?.success_url === 'string';\n}","tryCatchPattern":null,"preventionTips":["Sync the signup tier to Stripe before paid signup.","Confirm the cadence option is valid for the tier.","Wait for the fake checkout page to load before completing checkout."],"tags":["stripe","e2e","checkout","signup","subscriptions"],"backgroundTag":null,"analyzedSha":"47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe","analyzedAt":"2026-08-13T01:25:26.651Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}