Stirling-Tools/Stirling-PDF · error · Error

Failed to create checkout session: ${error.message}

Error message

Failed to create checkout session: ${error.message}

What it means

Thrown by createCheckoutSession when supabase.functions.invoke('create-checkout', ...) returns a non-null error. Like other Supabase edge-function calls, invoke resolves with {data, error}; a non-null error means the create-checkout function failed — bad Stripe keys, invalid lookup_key, missing installation_id, or a function-level exception. The thrown Error wraps error.message for the caller.

Source

Thrown at frontend/editor/src/proprietary/services/licenseService.ts:371

        requires_seats: request.requires_seats,
        seat_count: request.seat_count || 1,
        email: request.email,
        callback_base_url: baseUrl,
        ui_mode: checkoutMode,
        // For hosted checkout, provide success/cancel URLs
        success_url:
          checkoutMode === "hosted"
            ? `${settingsUrl}?session_id={CHECKOUT_SESSION_ID}&payment_status=success`
            : undefined,
        cancel_url:
          checkoutMode === "hosted"
            ? `${settingsUrl}?payment_status=canceled`
            : undefined,
      },
    });

    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.",
      );

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Read error.message — Stripe errors include the Stripe code (e.g. resource_missing, invalid_request).
  2. Confirm the create-checkout function is deployed with STRIPE_SECRET_KEY set.
  3. Validate the request.lookup_key against SELF_HOSTED_LOOKUP_KEYS and ensure the price is active in Stripe.
  4. Ensure installation_id was fetched (getInstallationId) and passed for self-hosted checkout.

Example fix

// before
const data = await licenseService.createCheckoutSession(req);

// after
try {
  const data = await licenseService.createCheckoutSession(req);
  redirectToCheckout(data);
} catch (e) {
  showToast(e instanceof Error ? e.message : 'Checkout failed');
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!req.lookup_key || !SELF_HOSTED_LOOKUP_KEYS.includes(req.lookup_key)) {
  setError('Invalid plan selection');
  return;
}
if (req.installation_id == null) req.installation_id = await licenseService.getInstallationId();

Type guard

export function isValidCheckoutRequest(r: CheckoutSessionRequest): boolean {
  return Boolean(r.lookup_key) && SELF_HOSTED_LOOKUP_KEYS.includes(r.lookup_key);
}

Try / catch

try {
  const data = await licenseService.createCheckoutSession(req);
  redirectToCheckout(data);
} catch (e) {
  showToast(e instanceof Error ? e.message : 'Checkout failed');
}

Prevention

When it happens

Trigger: create-checkout edge function lacks STRIPE_SECRET_KEY; the lookup_key in the request doesn't match a Stripe price; installation_id missing or malformed; Stripe rejects the session (blocked currency, inactive product); function throws on an unhandled code path.

Common situations: Stripe product for the lookup key is archived; currency/region mismatch; edge function deployed without secrets; Supabase project outage; malformed CheckoutSessionRequest from the UI.

Related errors


AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13). Data as JSON: /api/errors/99c92230fae25ec6. Report an issue: GitHub.