Stirling-Tools/Stirling-PDF · warning · Error
Supabase is not configured. Please use static plans instead.
Error message
Supabase is not configured. Please use static plans instead.
What it means
Thrown by licenseService.getPlans when Supabase isn't configured (isSupabaseConfigured is false or the supabase client is null). Plans/pricing are fetched live from Stripe via a Supabase edge function (stripe-price-lookup), so without Supabase the dynamic pricing path is impossible. The message explicitly points callers to the static plans fallback so the UI can still render tiers.
Source
Thrown at frontend/editor/src/proprietary/services/licenseService.ts:123
const licenseService = {
/**
* Get available plans with pricing for the specified currency.
*
* Feature and highlight labels are passed in by the caller (a React hook /
* context that resolves them via `usePlanFeatures` / `usePlanHighlights`),
* which keeps this service free of React/i18n dependencies while still
* returning fully localized plan content.
*/
async getPlans(
planFeatures: PlanFeaturesMap,
planHighlights: PlanHighlightsMap,
currency: string = "usd",
): Promise<PlansResponse> {
try {
// Check if Supabase is configured
if (!isSupabaseConfigured || !supabase) {
throw new Error(
"Supabase is not configured. Please use static plans instead.",
);
}
// Fetch all self-hosted prices from Stripe
const { data, error } = await supabase.functions.invoke<{
prices: Record<
string,
{
unit_amount: number;
currency: string;
lookup_key: string;
}
>;
missing: string[];
}>("stripe-price-lookup", {
body: {
lookup_keys: SELF_HOSTED_LOOKUP_KEYS,View on GitHub (pinned to 9ef20dcab8)
Solutions
- Catch the error and fall back to the static plan definitions (the message tells you to), as the caller (usePlanFeatures/usePlanHighlights context) is expected to do.
- Set VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY in the active env layer if you want live Stripe pricing.
- Gate the dynamic-pricing UI behind isSupabaseConfigured so getPlans is only called when it can succeed.
Example fix
// before
const { plans } = await licenseService.getPlans(features, highlights);
// after
let plans;
try {
({ plans } = await licenseService.getPlans(features, highlights));
} catch (e) {
if (/not configured/i.test(e.message)) plans = STATIC_PLANS;
else throw e;
} Defensive patterns
Strategy: validation
Validate before calling
import { isSupabaseConfigured } from "@app/services/supabaseClient";
if (!isSupabaseConfigured) {
// use static plans; don't call getPlans
} Type guard
export function canFetchDynamicPlans(): boolean {
return isSupabaseConfigured;
} Try / catch
try {
return await licenseService.getPlans(features, highlights, currency);
} catch (e) {
if (/not configured/i.test(e instanceof Error ? e.message : "")) {
return { plans: STATIC_PLANS };
}
throw e;
} Prevention
- Gate the dynamic-pricing code path on isSupabaseConfigured.
- Always implement the static-plans fallback the error message directs you to.
- Keep VITE_SUPABASE_URL/VITE_SUPABASE_ANON_KEY in the committed mode env files for self-hosted builds that need live pricing.
When it happens
Trigger: getPlans() called in a self-hosted build without Supabase env vars set; the supabaseClient module's isSupabaseConfigured flag is false because VITE_SUPABASE_URL/KEY are missing; calling getPlans in a build flavor that intentionally omits Supabase.
Common situations: Self-hosted deploy without the Supabase env vars configured; dev running the editor without a .env.local containing the Supabase keys; an OSS/core build that shouldn't hit licensing at all.
Related errors
- Failed to fetch plans: ${error.message}
- No pricing data returned
- Supabase is not configured. Checkout is not available.
- Supabase is not configured. Billing portal is not available.
- Failed to create checkout session: ${error.message}
AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13).
Data as JSON: /api/errors/861beda3b1e6e51f.
Report an issue: GitHub.