Stirling-Tools/Stirling-PDF · error · Error
Edge function returned no client_secret
Error message
Edge function returned no client_secret
What it means
Thrown by createCheckoutSession() in billing.ts when the create-checkout-session Supabase edge function returns data that has neither a client_secret nor a url. The function checks client_secret first, then url (hosted fallback), and only throws if both are absent. This indicates the edge function returned a success response with an incomplete payload.
Source
Thrown at frontend/editor/src/saas/services/billing.ts:60
...(params.billingOwnerEmail
? { billing_owner_email: params.billingOwnerEmail }
: {}),
},
});
if (error) {
throw error;
}
if (data?.client_secret) {
return {
clientSecret: data.client_secret,
mock: Boolean(data.mock) || data.client_secret.startsWith("cs_mock_"),
};
}
if (data?.url) {
return { url: data.url };
}
throw new Error("Edge function returned no client_secret");
}
/**
* The Stripe publishable key for embedded checkout. On the web this is the
* build-time {@code VITE_STRIPE_PUBLISHABLE_KEY}.
*/
export function getStripePublishableKey(): string {
return import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY ?? "";
}
/**
* Mint a Stripe Customer Portal session via the PAYG
* {@code create-customer-portal-session} edge function (its RPC enforces team
* membership). return_url is the current location so Stripe brings the user
* back to this page on close.
*/
export async function createPortalSession(
params: PortalParams,View on GitHub (pinned to 9ef20dcab8)
Solutions
- Check the create-checkout-session edge function logs in the Supabase dashboard
- Verify STRIPE_SECRET_KEY is set in the edge function's environment variables
- Confirm the team_id is valid and the current user is a member of that team
- Verify the currency and price configuration in Stripe match what the edge function expects
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify team has a valid ID before checkout
if (!params.teamId) {
throw new Error('A valid team is required to start checkout');
} Type guard
function hasCheckoutSecret(data: unknown): data is { client_secret: string; mock?: boolean } {
return (
typeof data === 'object' &&
data !== null &&
typeof (data as any).client_secret === 'string'
);
} Try / catch
try {
const session = await createCheckoutSession({ teamId, currency });
if (session.clientSecret) {
setClientSecret(session.clientSecret);
} else if (session.url) {
openExternal(session.url);
}
} catch (e) {
const msg = e instanceof Error ? e.message : 'Checkout failed to start';
setError(msg);
} Prevention
- Verify STRIPE_SECRET_KEY is set in the create-checkout-session edge function environment
- Confirm the team_id is valid and the user is a member before initiating checkout
- Test the edge function end-to-end with a known-good team_id in the Supabase dashboard
- Monitor the edge function for Stripe API errors that produce incomplete responses
When it happens
Trigger: The edge function partially succeeds — it receives the request but fails to create a Stripe Checkout Session, returning an object without client_secret or url. This happens when STRIPE_SECRET_KEY is missing (Stripe SDK throws and the function swallows it), the team_id is invalid, or the Stripe API returns an error that the function wraps without populating the expected fields.
Common situations: STRIPE_SECRET_KEY not configured in the edge function environment; team_id doesn't correspond to a valid team; Stripe API error (invalid currency, missing price) swallowed by the edge function; edge function deployed in test/mock mode returning an empty object.
Related errors
- create-checkout-session failed
- create-checkout-session returned neither client_secret nor U
- No pricing data returned
- serverMessage || error?.message || Failed to delete account
- data?.error ?? Portal session response missing url
AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13).
Data as JSON: /api/errors/2577fd891dfc8732.
Report an issue: GitHub.