knadh/listmonk · error
missing validationCode in subscription payload
Error message
missing validationCode in subscription payload
What it means
After extracting the event data map, ProcessSubscription reads data["validationCode"] and returns this error when it is empty or missing. Azure's subscription validation handshake requires echoing back this code as validationResponse; without it the subscription cannot be validated.
Source
Thrown at internal/bounce/webhooks/azure.go:82
// Validation code arrives in the first event for subscription validation flow.
var payload map[string]json.RawMessage
if err := json.Unmarshal(events[0].RawData, &payload); err != nil {
return nil, fmt.Errorf("error reading validation payload: %v", err)
}
rawData, ok := payload["data"]
if !ok {
return nil, errors.New("missing event data")
}
var data map[string]string
if err := json.Unmarshal(rawData, &data); err != nil {
return nil, fmt.Errorf("error reading validation data: %v", err)
}
code := strings.TrimSpace(data["validationCode"])
if code == "" {
return nil, errors.New("missing validationCode in subscription payload")
}
res, _ := json.Marshal(map[string]string{
"validationResponse": code,
})
return json.RawMessage(res), nil
}
// ProcessBounce parses Azure Event Grid email delivery events and returns bounce entries.
func (a *Azure) ProcessBounce(req *http.Request, b []byte) ([]models.Bounce, error) {
if err := a.verifyAuth(req); err != nil {
return nil, err
}
events, err := parseAzureEvents(b)
if err != nil {
return nil, err
}View on GitHub (pinned to 670c01717d)
Solutions
- Register the Event Grid subscription so a genuine SubscriptionValidationEvent containing validationCode is delivered (use the Azure portal/CLI handshake, not a fabricated payload).
- Check the delivered event JSON and confirm data.validationCode is present and non-empty.
- If testing, include a non-empty validationCode in the data map.
- Confirm no intermediary transformation is dropping the validationCode field.
Example fix
// before
curl -X POST https://host/webhooks/azure -d '{"data":{}}'
// after
curl -X POST https://host/webhooks/azure -d '{"data":{"validationCode":"abc123"}}' Defensive patterns
Strategy: validation
Validate before calling
var probe struct {
Data struct {
ValidationCode string `json:"validationCode"`
} `json:"data"`
}
if json.Unmarshal(rawData, &probe) != nil || strings.TrimSpace(probe.Data.ValidationCode) == "" {
// invalid validation payload; do not call ProcessSubscription
} Type guard
func hasValidationCode(raw json.RawMessage) bool {
var d struct {
ValidationCode string `json:"validationCode"`
}
if json.Unmarshal(raw, &d) != nil { return false }
return strings.TrimSpace(d.ValidationCode) != ""
} Try / catch
res, err := azure.ProcessSubscription(body)
if err != nil {
if strings.Contains(err.Error(), "missing validationCode") {
return echo.NewHTTPError(http.StatusBadRequest, "invalid validation event")
}
return err
} Prevention
- Register the subscription via the Azure portal/CLI so a genuine handshake event is delivered.
- Include a non-empty validationCode when testing manually.
- Ensure proxies/queues preserve all fields of the event data.
- Check Azure retries did not deliver truncated events.
When it happens
Trigger: A subscription validation event arrives whose data map has an empty or absent validationCode field — e.g. a manually crafted test payload, an event from a non-validation source routed to this handler, or whitespace-only validationCode (it is TrimSpace'd before the check).
Common situations: Testing the webhook with fake validation events lacking validationCode; Azure retries where the event was truncated; forwarding validation events through a queue/proxy that strips fields.
Related errors
- empty event payload
- missing event data
- missing azure event grid request context
- invalid azure event grid shared secret
- error reading validation data: %v
AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01).
Data as JSON: /api/errors/315c5b8db12459e0.
Report an issue: GitHub.