{"record":{"id":"bc717efe0c15b856","repo":"koala73/worldmonitor","slug":"checkout-failed-msg","errorCode":null,"errorMessage":"Checkout failed: ${msg}","messagePattern":"Checkout failed: (.+?)","errorType":"exception","errorClass":"ConvexError","httpStatus":null,"severity":"error","filePath":"convex/payments/checkout.ts","lineNumber":330,"sourceCode":"            `[checkout] Dodo 429 for user=${user.userId} product=${args.productId}; retrying in ${delayMs}ms`,\n          ),\n      },\n    );\n    if (isCheckoutRateLimitedOutcome(result)) {\n      console.warn(\n        `[checkout] Dodo rate limited checkout creation for user=${user.userId} product=${args.productId} after bounded retry (<=${CHECKOUT_RATE_LIMIT_MAX_ATTEMPTS} attempts); retry after ${result.retryAfterSeconds}s`,\n      );\n      return result;\n    }\n    return anonymousClaimToken\n      ? { ...result, anonymous_claim_token: anonymousClaimToken }\n      : result;\n  } catch (err) {\n    const msg = err instanceof Error ? err.message : String(err);\n    console.error(\n      `[checkout] createCheckout failed for user=${user.userId} product=${args.productId}: ${msg}`,\n    );\n    throw new ConvexError(`Checkout failed: ${msg}`);\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Public action: authenticated via Convex/Clerk auth\n// ---------------------------------------------------------------------------\n\nexport const createCheckout = action({\n  args: {\n    productId: v.string(),\n    returnUrl: v.optional(v.string()),\n    discountCode: v.optional(v.string()),\n    referralCode: v.optional(v.string()),\n    // \"Start a new checkout anyway\" — skips ONLY the pending-payment guard\n    // (#4438). The subscription guard still applies.\n    bypassPendingGuard: v.optional(v.boolean()),\n  },\n  handler: async (ctx, args) => {","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/koala73/worldmonitor/blob/ffec79ac339946fd2d24e85845da5755dcaa534b/convex/payments/checkout.ts#L312-L348","documentation":"Catch-all in `_createCheckoutSession`: any error thrown by the Dodo Payments provider call (after bounded rate-limit retry) is logged server-side as `[checkout] createCheckout failed` and re-thrown as a ConvexError with the underlying message interpolated. This preserves the public action's contract of rejecting provider failures via the error channel.","triggerScenarios":"The Dodo checkout-creation call raises: invalid productId, expired/invalid discount or referral code, Dodo API error response, network/transport failure, or a non-Error exception. The interpolated `msg` carries the specifics.","commonSituations":"Invalid productId not in the catalog; expired discount code; Dodo provider outage; malformed customer data; rate-limit retries already exhausted and re-surfaced here.","solutions":["Inspect the interpolated `msg` and the server log line `[checkout] createCheckout failed for user=... product=...: <msg>` for the root cause","Verify the productId resolves via resolveProductToPlan in the product catalog","Validate discountCode/referralCode before submitting if applicable","Retry once if the msg indicates a transient network/provider error; escalate if persistent"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Validate product/discount inputs before checkout to reduce provider failures.\nconst product = resolveProductToPlan(args.productId);\nif (!product) { /* block: unknown productId */ }","typeGuard":null,"tryCatchPattern":"try {\n  const result = await convex.action(api.payments.checkout.createCheckout, args);\n} catch (err) {\n  // err.message starts with 'Checkout failed: ' + provider detail\n  // inspect the server log [checkout] createCheckout failed for user=... product=...\n  if (/rate/i.test(err.message)) { /* back off */ } else { /* surface detail */ }\n}","preventionTips":["Validate productId against the catalog client-side before checkout","Surface the interpolated provider message to aid diagnosis","Retry only when the message indicates a transient error"],"tags":["payments","checkout","dodo","provider","error-handling"],"backgroundTag":null,"analyzedSha":"ffec79ac339946fd2d24e85845da5755dcaa534b","analyzedAt":"2026-08-12T11:24:56.012Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}