knadh/listmonk · error
error reading validation data: %v
Error message
error reading validation data: %v
What it means
ProcessSubscription validates Azure Event Grid subscription handshake requests. After parsing the event array, it extracts the `data` field of the first event and unmarshals it into map[string]string. This error is thrown when that `data` object cannot be decoded as a flat JSON object of string values — meaning the payload is not a well-formed subscription validation event.
Source
Thrown at internal/bounce/webhooks/azure.go:77
}
if len(events) == 0 {
return nil, errors.New("empty event payload")
}
// 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
}View on GitHub (pinned to 670c01717d)
Solutions
- Ensure only Event Grid 'Microsoft.EventGrid.SubscriptionValidationEvent' payloads are POSTed to the subscription-validation handler; route delivery-report events to ProcessBounce instead.
- Validate the incoming body is a JSON array whose first element contains data.validationCode as a string before calling ProcessSubscription.
- Log the raw request body on failure to inspect the actual shape of the `data` field.
- Check the Event Grid subscription is configured for the Azure Communication Services email events schema you expect.
Example fix
// before: posting a delivery-report event to the validation endpoint
body := `[{"eventType":"Microsoft.Communication.EmailDeliveryReportReceived","data":{"recipient":"a@b.com","status":"Failed"}}]`
res, err := azure.ProcessSubscription([]byte(body)) // error reading validation data
// after: post a proper validation event
body := `[{"eventType":"Microsoft.EventGrid.SubscriptionValidationEvent","data":{"validationCode":"abc123"}}]`
res, err := azure.ProcessSubscription([]byte(body)) // returns {"validationResponse":"abc123"} Defensive patterns
Strategy: validation
Validate before calling
func isValidSubscriptionValidation(body []byte) bool {
var evs []struct {
Data struct {
ValidationCode string `json:"validationCode"`
} `json:"data"`
}
return json.Unmarshal(body, &evs) == nil && len(evs) > 0 && evs[0].Data.ValidationCode != ""
} Type guard
func isStringMap(m json.RawMessage) bool {
var v map[string]string
return json.Unmarshal(m, &v) == nil
} Try / catch
res, err := azure.ProcessSubscription(body)
if err != nil {
log.Printf("subscription validation failed: %v; body=%s", err, body)
http.Error(w, "invalid subscription validation payload", http.StatusBadRequest)
return
} Prevention
- Only route Event Grid subscription-validation events to ProcessSubscription; use a separate route for bounce events.
- Inspect the eventType field before dispatching to a handler.
- Keep a captured real Event Grid validation payload as an integration test fixture.
When it happens
Trigger: Calling ProcessSubscription with a body whose first event's `data` field is absent-but-typed-differently, a nested object (e.g. a real EmailDeliveryReport data payload with structured fields instead of flat strings), an array, or a JSON literal like a number/string/bool rather than an object.
Common situations: Routing bounce notifications (Microsoft.Communication.EmailDeliveryReportReceived events) to the subscription-validation endpoint by mistake; Event Grid re-sending validation with a schema version whose data contains non-string fields; a proxy or test curl command posting hand-crafted JSON; Azure retrying an old event format after provider schema updates.
Related errors
- empty event payload
- error unmarshalling azure notification array: %v
- error unmarshalling azure event: %v
- missing event data
- missing validationCode in subscription payload
AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01).
Data as JSON: /api/errors/42e3e587a7b0925c.
Report an issue: GitHub.