Common Webhook Errors and How to Fix Them
Webhooks fail in a handful of predictable ways. Here are the errors developers hit most often, what causes each, and how to fix it.
1. Signature verification fails
Symptom: the request arrives but your verification check rejects it.
Cause: almost always you're hashing a re-serialized parsed body instead of the raw bytes the provider signed. Web frameworks parse JSON and re-stringify it, changing the bytes. Other causes: wrong encoding (hex vs base64), or the wrong secret (test vs live).
Fix: capture the raw request body before any JSON parsing and hash exactly that. See verifying webhook signatures.
2. The endpoint times out
Symptom: the provider marks deliveries as failed; your logs show the work started but the provider gave up.
Cause: your handler does slow work — database writes, sending email, calling other APIs — before responding. Most providers expect a response within a few seconds.
Fix: respond 200 immediately, then process the event asynchronously (a queue, a background job). Acknowledge first, work later.
3. Duplicate deliveries
Symptom: the same event is processed twice — two receipts, two charges, two records.
Cause: webhook delivery is at-least-once. If your endpoint is slow or briefly errors, the provider retries — and the original may have actually succeeded.
Fix: make your handler idempotent. Every webhook has a unique id (X-GitHub-Delivery, X-Shopify-Webhook-Id, the Stripe event id). Record processed ids and skip duplicates.
4. Works locally, fails in production (or vice versa)
Symptom: the integration works in one environment but not the other.
Cause: each environment has its own webhook configuration and its own signing secret. Code using the wrong environment's secret rejects every request.
Fix: store each environment's secret separately and make sure the running code reads the right one.
5. Truncated or empty payload
Symptom: the body arrives empty or cut off.
Cause: a reverse proxy (Nginx, CloudFront, API Gateway) with a body-size limit set too low, or middleware that consumes the body stream before your handler reads it.
Fix: raise proxy body limits, and ensure body-parsing middleware runs in the right order.
6. 4xx/5xx from your endpoint
Symptom: the provider's delivery log shows red failures.
Cause: your handler threw an exception, hit an auth wall, or the route doesn't exist.
Fix: check the response body the provider recorded. A 404 means a wrong URL; a 401/403 means auth middleware is blocking the provider; a 500 means your code threw — and the provider will retry, so fix it before the retry window closes.
7. The handler never fires at all
Symptom: nothing happens — no logs, no errors.
Cause: the webhook was never registered, points at the wrong URL, or isn't subscribed to the event you expect.
Fix: this is where a webhook tester earns its keep. Point the provider at a capture URL and fire an event. If nothing shows up, the problem is the provider config. If it does show up, the problem is your endpoint.
The fastest webhook debugging move: capture the real request on a URL you control, so you can see exactly what's being sent before blaming your code.