{"record":{"id":"4a107cc48101bbca","repo":"Stirling-Tools/Stirling-PDF","slug":"create-checkout-session-failed","errorCode":null,"errorMessage":"create-checkout-session failed","messagePattern":"create-checkout-session failed","errorType":"exception","errorClass":"StripeFunctionError","httpStatus":null,"severity":"error","filePath":"frontend/editor/src/portal/billing/stripe.ts","lineNumber":285,"sourceCode":"export async function createCheckoutSession(\n  req: CheckoutSessionRequest,\n): Promise<CheckoutSession> {\n  const res = await invoke<CheckoutResponse>(\"create-checkout-session\", {\n    team_id: req.teamId,\n    currency: req.currency ?? \"usd\",\n    success_url: req.successUrl,\n    cancel_url: req.cancelUrl,\n    // The portal drives an in-page onComplete handler (the checkout modal stays open to\n    // finalise activation + nudge the linked instance), so tell the edge function not to\n    // redirect on completion. A redirect would reload the page, skip that finalize step, and\n    // make Stripe ignore onComplete entirely (console warns \"redirect_on_completion: always\").\n    redirect_on_completion: \"never\",\n    ...(req.billingOwnerEmail\n      ? { billing_owner_email: req.billingOwnerEmail }\n      : {}),\n  });\n  if (!res.success) {\n    throw new StripeFunctionError(\n      res.error ?? \"create-checkout-session failed\",\n    );\n  }\n  const alreadySubscribed = Boolean(res.already_subscribed);\n  const redirectUrl = alreadySubscribed\n    ? (res.portal_url ?? null)\n    : (res.url ?? null);\n  const clientSecret = alreadySubscribed ? null : (res.client_secret ?? null);\n  if (!clientSecret && !redirectUrl) {\n    throw new StripeFunctionError(\n      \"create-checkout-session returned neither client_secret nor URL\",\n    );\n  }\n  return {\n    clientSecret,\n    redirectUrl,\n    alreadySubscribed,\n  };","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/portal/billing/stripe.ts#L267-L303","documentation":"Fallback thrown by createCheckoutSession when the edge function returns res.success === false but no res.error field. It means the function explicitly reported failure yet omitted an explanation, so the client substitutes a generic message.","triggerScenarios":"create-checkout-session responds { success: false } (no error string). The right-hand operand of `res.error ?? fallback`, so it only fires when error is null/undefined/empty.","commonSituations":"Edge function hit an error branch that returns { success: false } without setting error; a Stripe API failure inside the function was swallowed; a refactored response shape dropped the error field.","solutions":["Open the create-checkout-session edge function logs in the Supabase dashboard to find the real failure branch.","Ensure every failure branch in the function returns { success: false, error: '<detail>' }.","Verify Stripe secret key + price/price-tier config the function reads.","Catch StripeFunctionError at the call site and surface a user-facing message; retry after fixing config."],"exampleFix":"// edge function — before\nreturn new Response(JSON.stringify({ success: false }), { status: 200 });\n\n// after\nreturn new Response(\n  JSON.stringify({ success: false, error: 'Stripe price not found for currency' }),\n  { status: 200, headers: { 'Content-Type': 'application/json' } },\n);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isCheckoutFailure(res: CheckoutResponse): res is CheckoutResponse & { success: false } {\n  return res.success === false;\n}","tryCatchPattern":"try {\n  const { clientSecret, redirectUrl } = await createCheckoutSession(req);\n  startEmbeddedCheckout(clientSecret, redirectUrl);\n} catch (e) {\n  if (e instanceof StripeFunctionError) {\n    notifications.show({ message: e.message, color: \"red\" });\n  } else throw e;\n}","preventionTips":["Ensure every failure branch in create-checkout-session returns { success: false, error }.","Verify the Stripe secret key + price config the function reads.","Always catch StripeFunctionError at the checkout call site and surface e.message."],"tags":["billing","stripe","supabase","edge-function","checkout","contract"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}