{"record":{"id":"b4986820f2bbe733","repo":"Stirling-Tools/Stirling-PDF","slug":"data-error-portal-session-response-missing-url","errorCode":null,"errorMessage":"data?.error ?? Portal session response missing url","messagePattern":"data\\?\\.error \\?\\? Portal session response missing url","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/editor/src/saas/services/billing.ts","lineNumber":90,"sourceCode":" * Mint a Stripe Customer Portal session via the PAYG\n * {@code create-customer-portal-session} edge function (its RPC enforces team\n * membership). return_url is the current location so Stripe brings the user\n * back to this page on close.\n */\nexport async function createPortalSession(\n  params: PortalParams,\n): Promise<PortalSession> {\n  const { data, error } = await supabase.functions.invoke<{\n    url?: string;\n    error?: string;\n  }>(\"create-customer-portal-session\", {\n    body: { team_id: params.teamId, return_url: window.location.href },\n  });\n  if (error) {\n    throw error;\n  }\n  if (!data?.url) {\n    throw new Error(data?.error ?? \"Portal session response missing url\");\n  }\n  return { url: data.url };\n}\n","sourceCodeStart":72,"sourceCodeEnd":94,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/saas/services/billing.ts#L72-L94","documentation":"Thrown by createPortalSession() in billing.ts when the create-customer-portal-session edge function returns data without a url field. The error message prioritizes data.error (a server-provided reason) and falls back to a generic string. The Stripe Customer Portal requires an existing Stripe customer, so this commonly fires when the team has never subscribed.","triggerScenarios":"The team_id has no associated Stripe customer record; the edge function encounters a Stripe API error; the Stripe customer portal is not configured in the Stripe dashboard; the edge function returns an error string in data.error.","commonSituations":"User clicks 'manage billing' before ever subscribing (no Stripe customer exists); Stripe Customer Portal not configured in Stripe Dashboard > Settings > Billing > Customer Portal; edge function STRIPE_SECRET_KEY missing; team_id not linked to a Stripe customer ID in the database.","solutions":["Read data.error if present for the server-provided reason (e.g. 'No Stripe customer found')","Only show the 'manage billing' / customer portal button for teams that have an active Stripe subscription","Verify the Stripe Customer Portal is configured in the Stripe dashboard","Check the create-customer-portal-session edge function logs"],"exampleFix":"// before\nif (!data?.url) {\n  throw new Error(data?.error ?? \"Portal session response missing url\");\n}\n\n// after (in the caller)\ntry {\n  const { url } = await createPortalSession({ teamId });\n  openExternal(url);\n} catch (e) {\n  if (e.message.includes('No Stripe customer')) {\n    setShowSubscribePrompt(true); // guide user to subscribe first\n  }\n}","handlingStrategy":"validation","validationCode":"// Only show the customer portal button if the team has a Stripe customer\nif (!currentTeam?.hasStripeCustomer) {\n  setShowSubscribePromptInstead(true);\n  return;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const { url } = await createPortalSession({ teamId });\n  openExternal(url);\n} catch (e) {\n  const msg = e instanceof Error ? e.message : '';\n  if (msg.includes('No Stripe customer') || msg.includes('missing url')) {\n    setPortalError('No billing account found. Please subscribe first.');\n  } else {\n    setPortalError(msg);\n  }\n}","preventionTips":["Only offer the customer portal to teams that have an active Stripe subscription","Verify the Stripe Customer Portal is configured in Stripe Dashboard > Settings > Billing > Customer Portal","Check that the edge function has STRIPE_SECRET_KEY configured","Surface data.error from the edge function to guide the user when available"],"tags":["billing","stripe","portal","edge-function","supabase","saas"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}