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.
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
- Invalid signature
- Payment redirect URLs cannot be validated…
- Invalid payload
- success_url and cancel_url must match the platform frontend…
- 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.
Appendix: 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)