Stirling-Tools/Stirling-PDF · error · Error
No pricing data returned
Error message
No pricing data returned
What it means
Thrown by getPlans when the stripe-price-lookup invocation succeeded (no error) but the returned data is null or has no prices field. This guards against a malformed/degenerate edge-function response — the lookup technically ran but produced nothing usable, so building plan tiers is impossible. Distinct from error 167 because there was no FunctionsError, just empty data.
Source
Thrown at frontend/editor/src/proprietary/services/licenseService.ts:151
unit_amount: number;
currency: string;
lookup_key: string;
}
>;
missing: string[];
}>("stripe-price-lookup", {
body: {
lookup_keys: SELF_HOSTED_LOOKUP_KEYS,
currency,
},
});
if (error) {
throw new Error(`Failed to fetch plans: ${error.message}`);
}
if (!data || !data.prices) {
throw new Error("No pricing data returned");
}
// Log missing prices for debugging
if (data.missing && data.missing.length > 0) {
console.warn(
"Missing Stripe prices for lookup keys:",
data.missing,
"in currency:",
currency,
);
}
// Build price map for easy access
const priceMap = new Map<
string,
{ unit_amount: number; currency: string }
>();
for (const [lookupKey, priceData] of Object.entries(data.prices)) {View on GitHub (pinned to 9ef20dcab8)
Solutions
- Log/inspect the actual returned data shape from the edge function to confirm whether prices or only missing is present.
- Ensure all SELF_HOSTED_LOOKUP_KEYS have active prices in Stripe so the function returns a non-empty prices map.
- Update the edge function to always return a prices object (even if empty) and check missing for diagnosis.
- Fall back to static plans at the caller if dynamic pricing is optional.
Example fix
// before
if (!data || !data.prices) throw new Error("No pricing data returned");
// after — also log missing keys for diagnosis, then fall back
if (!data || !data.prices) {
console.warn('stripe-price-lookup returned no prices', data?.missing);
return { plans: buildStaticPlans(features, highlights) };
} Defensive patterns
Strategy: fallback
Validate before calling
// caller cannot pre-validate response shape; ensure keys exist in Stripe so the function returns prices
Try / catch
try {
return await licenseService.getPlans(features, highlights, currency);
} catch (e) {
if (/No pricing data returned/.test(e instanceof Error ? e.message : "")) {
return { plans: STATIC_PLANS };
}
throw e;
} Prevention
- Keep the edge function's return shape under test so prices is always present on success.
- Register every SELF_HOSTED_LOOKUP_KEYS as an active Stripe price.
- Log the missing array returned by the function when prices come back empty.
When it happens
Trigger: The edge function returns {} or null on success (e.g. it silently returned early); it returns {missing:[...]} with no prices because no lookup keys matched; a response-shape change in the function that dropped the prices field; the function returned a 2xx with an empty body.
Common situations: Edge function deployed in a mode that returns early when Stripe has no matching prices; lookup keys misconfigured so all are reported missing and prices omitted; a refactor of the function's return shape that the client hasn't caught up to.
Related errors
- Supabase is not configured. Please use static plans instead.
- Failed to fetch plans: ${error.message}
- No billing portal URL returned
- Supabase is not configured. Checkout 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/4d2a23ec5259fd01.
Report an issue: GitHub.