Significant-Gravitas/AutoGPT · critical · HTTPException
Webhook not configured
Error message
Webhook not configured
What it means
Raised (503) by POST /credits/stripe_webhook when settings.secrets.stripe_webhook_secret is empty. The comment makes the security rationale explicit: with an empty secret, an attacker could compute a valid HMAC signature over the same empty key and forge webhook events (e.g. fake payment completions). All webhook deliveries are therefore rejected until the secret is configured.
Source
Thrown at autogpt_platform/backend/backend/api/features/v1.py:1426
"stripe_webhook: dedup release failed for event %s",
event_id,
exc_info=True,
)
@v1_router.post(
path="/credits/stripe_webhook", summary="Handle Stripe webhooks", tags=["credits"]
)
async def stripe_webhook(request: Request):
webhook_secret = settings.secrets.stripe_webhook_secret
if not webhook_secret:
# Guard: an empty secret allows HMAC forgery (attacker can compute a valid
# signature over the same empty key). Reject all webhook calls when unconfigured.
logger.error(
"stripe_webhook: STRIPE_WEBHOOK_SECRET is not configured — "
"rejecting request to prevent signature bypass"
)
raise HTTPException(status_code=503, detail="Webhook not configured")
# Get the raw request body
payload = await request.body()
# Get the signature header
sig_header = request.headers.get("stripe-signature")
try:
event = stripe.Webhook.construct_event(payload, sig_header, webhook_secret)
except ValueError:
# Invalid payload
raise HTTPException(status_code=400, detail="Invalid payload")
except stripe.SignatureVerificationError:
# Invalid signature
raise HTTPException(status_code=400, detail="Invalid signature")
# Defensive payload extraction. A malformed payload (missing/non-dict
# `data.object`, missing `id`) would otherwise raise KeyError/TypeError
# AFTER signature verification — which Stripe interprets as a deliveryView on GitHub (pinned to 9c8bb5550f)
Solutions
- Set STRIPE_WEBHOOK_SECRET to the signing secret of the webhook endpoint (Stripe Dashboard > Developers > Webhooks, or `stripe listen` output for local dev) and restart the backend.
- If the endpoint was recreated in Stripe, copy the NEW whsec_... value — secrets change per endpoint.
- Confirm the secret actually reaches the process (container env, secret mount) rather than only existing in CI.
Example fix
# before # STRIPE_WEBHOOK_SECRET= (empty) # after STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxx
Defensive patterns
Strategy: validation
Validate before calling
# pre-deploy check
import os
assert os.environ.get('STRIPE_WEBHOOK_SECRET', '').startswith('whsec_'), \
'STRIPE_WEBHOOK_SECRET missing — webhook endpoint will 503' Try / catch
Stripe webhook 503 is server-side misconfiguration; callers (Stripe) will retry automatically — monitor delivery failures in the Stripe dashboard rather than catching client-side.
Prevention
- Add a startup assertion or readiness probe that STRIPE_WEBHOOK_SECRET is set and starts with whsec_.
- Automate copying the secret from `stripe listen` into local .env.
- When recreating webhook endpoints in Stripe, treat secret rotation as part of the deploy.
When it happens
Trigger: Stripe sends a webhook to an environment where STRIPE_WEBHOOK_SECRET is unset/empty — fresh deployments, local dev without the Stripe CLI secret, or a secrets migration that dropped the variable.
Common situations: New environment not registered in the Stripe dashboard; developer testing webhooks locally but forgetting to copy the `whsec_...` from `stripe listen`; Helm/K8s secret not mounted; rotated webhook endpoint in Stripe dashboard generating a new secret never propagated to the app.
Related errors
- Payment redirect URLs cannot be validated: frontend_base_url
- Invalid signature
- success_url and cancel_url must match the platform frontend
- Invalid payload
- chat_transport_not_configured
AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14).
Data as JSON: /api/errors/89241f15a097e1f8.
Report an issue: GitHub.