From 85a3b3e469f051840a27689c6222fc11d4e642bc Mon Sep 17 00:00:00 2001 From: kolaente Date: Thu, 9 Apr 2026 11:09:07 +0200 Subject: [PATCH] fix(webhook): return error from delivery listener on nil payload A nil payload signals data corruption or a version mismatch on the event bus, not a safe-to-drop condition. Returning an error lets the watermill retry middleware retry the message and eventually park it in the poison queue instead of silently acking it. --- pkg/models/listeners.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index d4e20be1c..fa97fa600 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -18,6 +18,7 @@ package models import ( "encoding/json" + "fmt" "strconv" "time" @@ -800,6 +801,9 @@ func (wdl *WebhookDeliveryListener) Name() string { // Special cases: // - If the webhook row no longer exists (deleted between fan-out and // delivery), Handle returns nil so the message is not retried. +// - A nil payload is treated as data corruption / version skew and +// returned as an error so the message is retried and eventually +// parked in the poison queue rather than silently dropped. // - Any other error is returned so the watermill retry middleware // retries this delivery with exponential backoff, and eventually // parks it in the poison queue if all retries fail. @@ -810,8 +814,7 @@ func (wdl *WebhookDeliveryListener) Handle(msg *message.Message) error { } if evt.Payload == nil { - log.Errorf("webhook delivery event for webhook %d has no payload", evt.WebhookID) - return nil + return fmt.Errorf("webhook delivery event for webhook %d has no payload", evt.WebhookID) } s := db.NewSession()