{"record":{"id":"8bb90f9fd338a4a8","repo":"Significant-Gravitas/AutoGPT","slug":"success-url-and-cancel-url-are-required-for-paid-t","errorCode":null,"errorMessage":"success_url and cancel_url are required for paid tier upgrades","messagePattern":"success_url and cancel_url are required for paid tier upgrades","errorType":"http","errorClass":"HTTPException","httpStatus":422,"severity":"warning","filePath":"autogpt_platform/backend/backend/api/features/v1.py","lineNumber":1297,"sourceCode":"                \"Unable to update your subscription right now. \"\n                \"Please try again or contact support.\"\n            ),\n        )\n    except stripe.StripeError as e:\n        logger.exception(\n            \"Stripe error modifying subscription for user %s: %s\", user_id, e\n        )\n        raise HTTPException(\n            status_code=502,\n            detail=(\n                \"Unable to update your subscription right now. \"\n                \"Please try again or contact support.\"\n            ),\n        )\n\n    # No active Stripe subscription → create Stripe Checkout Session.\n    if not request.success_url or not request.cancel_url:\n        raise HTTPException(\n            status_code=422,\n            detail=\"success_url and cancel_url are required for paid tier upgrades\",\n        )\n    # Open-redirect protection: both URLs must point to the configured frontend\n    # origin, otherwise an attacker could use our Stripe integration as a\n    # redirector to arbitrary phishing sites.\n    #\n    # Fail early with a clear 503 if the server is misconfigured (neither\n    # frontend_base_url nor platform_base_url set), so operators get an\n    # actionable error instead of the misleading \"must match the platform\n    # frontend origin\" 422 that _validate_checkout_redirect_url would otherwise\n    # produce when `allowed` is empty.\n    if not (settings.config.frontend_base_url or settings.config.platform_base_url):\n        logger.error(\n            \"update_subscription_tier: neither frontend_base_url nor \"\n            \"platform_base_url is configured; cannot validate checkout redirect URLs\"\n        )\n        raise HTTPException(","sourceCodeStart":1279,"sourceCodeEnd":1315,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/api/features/v1.py#L1279-L1315","documentation":"HTTP 422 from POST /credits/subscription when the user has no active Stripe subscription (so a new Checkout Session must be created) but the request omits success_url or cancel_url. The Stripe Checkout flow needs both redirect targets; without an existing subscription to modify, they are mandatory.","triggerScenarios":"First-time upgrade request (no active subscription) with request body lacking success_url and/or cancel_url, or either being an empty string.","commonSituations":"Frontend sending only success_url for a 'one-way' upgrade; API clients copying the modify-in-place request shape; empty-string defaults from form state; older clients predating the required field.","solutions":["Include both success_url and cancel_url in the request body for new paid-tier checkouts","Both URLs must also point at the configured frontend origin or they fail the open-redirect check","Ensure the server has frontend_base_url/platform_base_url configured so the origin allow-list is populated"],"exampleFix":"// before\n{ tier: \"PRO\", billing_cycle: \"monthly\" }\n\n// after\n{\n  tier: \"PRO\",\n  billing_cycle: \"monthly\",\n  success_url: \"https://app.example.com/billing/success\",\n  cancel_url: \"https://app.example.com/billing\"\n}","handlingStrategy":"validation","validationCode":"const status = await api.getSubscriptionStatus();\nconst needsCheckout = !status.hasActiveStripeSubscription;\nif (needsCheckout && (!successUrl || !cancelUrl)) throw new Error(\"success_url and cancel_url required\");","typeGuard":"function isValidCheckoutRequest(r: SubscriptionRequest, hasActiveSub: boolean): boolean {\n  return !hasActiveSub || Boolean(r.success_url && r.cancel_url);\n}","tryCatchPattern":null,"preventionTips":["Always include success_url and cancel_url for paid tiers","Ensure both URLs share the platform frontend origin (open-redirect guard)","Configure frontend_base_url on the server"],"tags":["stripe","checkout","validation","subscription","http-422"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}