After helping thousands of developers debug webhooks, we've seen the same mistakes over and over. These aren't bugs in your code — they're process mistakes that turn a 10-minute fix into a 3-hour ordeal.
Here are the five most common webhook debugging mistakes and how to avoid them.
Mistake #1: Re-triggering Webhooks Instead of Replaying
The mistake: Every time you need to test your webhook handler, you go back to Stripe's dashboard (or Shopify, or GitHub) and trigger a new test event. Change one line of code? Trigger another event. Add a log statement? Trigger another event.
Why it costs you hours: Each trigger takes 30-60 seconds. Do that 50 times while debugging, and you've lost 25-50 minutes just waiting. Plus, each test event has slightly different data (new IDs, timestamps), making it harder to compare behavior.
Capture the webhook once and replay it as many times as you need. Tools like HookReplay let you send the exact same payload to your localhost over and over, instantly.
Mistake #2: Not Logging the Raw Payload
The mistake: You parse the webhook payload immediately and only log processed data. When something goes wrong, you can't see what was actually received.
// Bad: Only logging processed data
app.post('/webhook', (req, res) => {
const event = JSON.parse(req.body);
console.log('Event type:', event.type); // Not enough!
// ...
});
Why it costs you hours: When a webhook fails, you need to see exactly what was sent. Was a field missing? Was it in an unexpected format? Without the raw payload, you're guessing.
Always log the raw payload before processing. In production, log to a structured logging system. During development, use a tool that captures and displays the full request.
// Good: Log raw payload first
app.post('/webhook', (req, res) => {
console.log('Raw webhook:', JSON.stringify(req.body));
console.log('Headers:', JSON.stringify(req.headers));
const event = JSON.parse(req.body);
// ...
});
Mistake #3: Not Handling Duplicate Webhooks
The mistake: Assuming each webhook will only be delivered once. Your code processes the same payment twice, creating duplicate orders or double-charging customers.
Why it costs you hours: This bug often doesn't show up in testing because you're only triggering webhooks manually. In production, webhook providers retry failed deliveries, and network issues can cause duplicates. Debugging production data corruption is painful.
This means you might receive the same webhook 2, 3, or even 10 times. Your code must handle this gracefully.
Implement idempotency. Store the webhook event ID and check if you've already processed it. Test by replaying the same webhook multiple times and verifying your code handles it correctly.
// Good: Check for duplicates
app.post('/webhook', async (req, res) => {
const event = JSON.parse(req.body);
// Check if already processed
const existing = await db.webhookEvents.findOne({ eventId: event.id });
if (existing) {
console.log('Duplicate webhook, skipping:', event.id);
return res.status(200).send('OK');
}
// Store event ID before processing
await db.webhookEvents.insert({ eventId: event.id, receivedAt: new Date() });
// Now process the event
// ...
});
Mistake #4: Not Testing Edge Cases
The mistake: Only testing the happy path. Your webhook handler works great
for payment_intent.succeeded, but crashes on payment_intent.payment_failed
or when a field is unexpectedly null.
Why it costs you hours: Edge cases show up in production at the worst times. A customer's payment fails, your webhook handler crashes, and now you're debugging at 2 AM.
Edit webhook payloads before replaying to test edge cases. What happens when
customer is null? When amount is 0? When there are 100 line items
instead of 1? Test these before they happen in production.
Common edge cases to test:
- Null or missing optional fields
- Empty arrays vs. arrays with many items
- Zero amounts, negative amounts
- Unicode characters in strings
- Very long strings
- Unexpected event types
Mistake #5: Debugging Without Breakpoints
The mistake: Relying entirely on console.log statements to debug webhooks.
Add a log, trigger the webhook, check the output, add another log, trigger again...
Why it costs you hours: Each iteration takes time. With breakpoints, you can inspect every variable at once, step through the code, and understand exactly what's happening.
Use capture-and-replay so you control when the webhook arrives. Set your breakpoint, start debugging, then trigger the replay. Step through your code at your own pace without worrying about timeouts.
The traditional problem with breakpoint debugging on webhooks is that the webhook provider times out while you're stepping through code. With replay-based debugging, this isn't an issue — you're in complete control.
Bonus: The Ultimate Webhook Debugging Checklist
Before you start debugging, make sure you have:
- Raw payload logging enabled
- The exact payload that caused the issue (captured or from logs)
- A way to replay the webhook without re-triggering
- Breakpoints set in your IDE
- Test cases for edge cases ready
- Idempotency handling in place
Summary
Most webhook debugging pain comes from process problems, not code problems. The five mistakes we covered:
- Re-triggering instead of replaying — Capture once, replay infinitely
- Not logging raw payloads — Always log before processing
- Not handling duplicates — Implement idempotency
- Not testing edge cases — Edit payloads to simulate failures
- Debugging without breakpoints — Use replay to control timing
Fix these process issues and you'll spend less time debugging and more time building.