{"record":{"id":"42e3e587a7b0925c","repo":"knadh/listmonk","slug":"error-reading-validation-data-v","errorCode":null,"errorMessage":"error reading validation data: %v","messagePattern":"error reading validation data: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/bounce/webhooks/azure.go","lineNumber":77,"sourceCode":"\t}\n\tif len(events) == 0 {\n\t\treturn nil, errors.New(\"empty event payload\")\n\t}\n\n\t// Validation code arrives in the first event for subscription validation flow.\n\tvar payload map[string]json.RawMessage\n\tif err := json.Unmarshal(events[0].RawData, &payload); err != nil {\n\t\treturn nil, fmt.Errorf(\"error reading validation payload: %v\", err)\n\t}\n\n\trawData, ok := payload[\"data\"]\n\tif !ok {\n\t\treturn nil, errors.New(\"missing event data\")\n\t}\n\n\tvar data map[string]string\n\tif err := json.Unmarshal(rawData, &data); err != nil {\n\t\treturn nil, fmt.Errorf(\"error reading validation data: %v\", err)\n\t}\n\n\tcode := strings.TrimSpace(data[\"validationCode\"])\n\tif code == \"\" {\n\t\treturn nil, errors.New(\"missing validationCode in subscription payload\")\n\t}\n\n\tres, _ := json.Marshal(map[string]string{\n\t\t\"validationResponse\": code,\n\t})\n\treturn json.RawMessage(res), nil\n}\n\n// ProcessBounce parses Azure Event Grid email delivery events and returns bounce entries.\nfunc (a *Azure) ProcessBounce(req *http.Request, b []byte) ([]models.Bounce, error) {\n\tif err := a.verifyAuth(req); err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/knadh/listmonk/blob/670c01717d48647093335cc23a6be6f4b79c3b6b/internal/bounce/webhooks/azure.go#L59-L95","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: posting a delivery-report event to the validation endpoint\nbody := `[{\"eventType\":\"Microsoft.Communication.EmailDeliveryReportReceived\",\"data\":{\"recipient\":\"a@b.com\",\"status\":\"Failed\"}}]`\nres, err := azure.ProcessSubscription([]byte(body)) // error reading validation data\n\n// after: post a proper validation event\nbody := `[{\"eventType\":\"Microsoft.EventGrid.SubscriptionValidationEvent\",\"data\":{\"validationCode\":\"abc123\"}}]`\nres, err := azure.ProcessSubscription([]byte(body)) // returns {\"validationResponse\":\"abc123\"}","handlingStrategy":"validation","validationCode":"func isValidSubscriptionValidation(body []byte) bool {\n    var evs []struct {\n        Data struct {\n            ValidationCode string `json:\"validationCode\"`\n        } `json:\"data\"`\n    }\n    return json.Unmarshal(body, &evs) == nil && len(evs) > 0 && evs[0].Data.ValidationCode != \"\"\n}","typeGuard":"func isStringMap(m json.RawMessage) bool {\n    var v map[string]string\n    return json.Unmarshal(m, &v) == nil\n}","tryCatchPattern":"res, err := azure.ProcessSubscription(body)\nif err != nil {\n    log.Printf(\"subscription validation failed: %v; body=%s\", err, body)\n    http.Error(w, \"invalid subscription validation payload\", http.StatusBadRequest)\n    return\n}","preventionTips":["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."],"tags":["azure","webhook","json","event-grid","validation"],"backgroundTag":"webhook-payload-schema-mismatch","analyzedSha":"670c01717d48647093335cc23a6be6f4b79c3b6b","analyzedAt":"2026-09-01T03:39:35.452Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}