Stirling-Tools/Stirling-PDF · error · Error
Supabase is not configured. Billing portal is not available.
Error message
Supabase is not configured. Billing portal is not available.
What it means
Thrown by createBillingPortalSession when Supabase isn't configured. The Stripe billing portal session is opened via the Supabase edge function manage-billing, so it requires the Supabase client. The guard fails fast with a message naming the unavailable capability (billing portal) so the UI can disable the 'Manage subscription' action.
Source
Thrown at frontend/editor/src/proprietary/services/licenseService.ts:387
if (error) {
throw new Error(`Failed to create checkout session: ${error.message}`);
}
return data as CheckoutSessionResponse;
},
/**
* Create a Stripe billing portal session for managing subscription
* Uses license key for self-hosted authentication
*/
async createBillingPortalSession(
returnUrl: string,
licenseKey: string,
): Promise<BillingPortalResponse> {
// Check if Supabase is configured
if (!isSupabaseConfigured || !supabase) {
throw new Error(
"Supabase is not configured. Billing portal is not available.",
);
}
const { data, error } = await supabase.functions.invoke("manage-billing", {
body: {
return_url: returnUrl,
license_key: licenseKey,
self_hosted: true, // Explicitly indicate self-hosted mode
},
});
if (error) {
throw new Error(
`Failed to create billing portal session: ${error.message}`,
);
}
View on GitHub (pinned to 9ef20dcab8)
Solutions
- Gate the 'Manage subscription' button on isSupabaseConfigured.
- Set VITE_SUPABASE_URL/VITE_SUPABASE_ANON_KEY in the active env layer.
- Catch the error and inform the user billing management isn't available in this mode.
Example fix
// before
const { url } = await licenseService.createBillingPortalSession(returnUrl, key);
// after
if (!isSupabaseConfigured) {
showToast(t('license.billingUnavailable'));
return;
}
const { url } = await licenseService.createBillingPortalSession(returnUrl, key); Defensive patterns
Strategy: validation
Validate before calling
if (!isSupabaseConfigured) {
showToast(t('license.billingUnavailable'));
return;
} Type guard
export function canOpenBillingPortal(): boolean {
return isSupabaseConfigured;
} Try / catch
try {
await licenseService.createBillingPortalSession(returnUrl, key);
} catch (e) {
if (/not configured/i.test(e instanceof Error ? e.message : "")) {
showToast(t('license.billingUnavailable'));
} else throw e;
} Prevention
- Gate the 'Manage subscription' button on isSupabaseConfigured.
- Set Supabase env vars where billing management is expected to work.
- Hide the action in flavors that intentionally omit Supabase.
When it happens
Trigger: User clicks 'Manage billing' in a build without Supabase configured; isSupabaseConfigured is false; calling the method from a flavor that intentionally omits Supabase.
Common situations: Self-hosted deploy without Supabase env vars; dev run without .env.local Supabase keys; manage-subscription button rendered when licensing backend is offline.
Related errors
- Supabase is not configured. Please use static plans instead.
- Supabase is not configured. Checkout is not available.
- Failed to create billing portal session: ${error.message}
- Supabase is not configured. Seat updates are not available.
- Failed to fetch plans: ${error.message}
AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13).
Data as JSON: /api/errors/4a6ccbac7b974821.
Report an issue: GitHub.