knadh/listmonk · error
error unmarshalling azure event: %v
Error message
error unmarshalling azure event: %v
What it means
After the body parses as a JSON array, parseAzureEvents unmarshals each element into the azureEvent struct (eventType + data). This error is thrown when an individual array element is not a valid JSON object or contains fields whose types conflict with the struct (e.g. `data` is a string instead of an object).
Source
Thrown at internal/bounce/webhooks/azure.go:190
func secretsEqual(expected, given string) bool {
if expected == "" || given == "" {
return false
}
return subtle.ConstantTimeCompare([]byte(expected), []byte(given)) == 1
}
func parseAzureEvents(b []byte) ([]azureEvent, error) {
var raws []json.RawMessage
if err := json.Unmarshal(b, &raws); err != nil {
return nil, fmt.Errorf("error unmarshalling azure notification array: %v", err)
}
events := make([]azureEvent, 0, len(raws))
for _, raw := range raws {
ev := azureEvent{RawData: raw}
if err := json.Unmarshal(raw, &ev); err != nil {
return nil, fmt.Errorf("error unmarshalling azure event: %v", err)
}
events = append(events, ev)
}
return events, nil
}
func mapAzureStatus(status, details string) (string, bool) {
s := strings.ToLower(strings.TrimSpace(status))
d := strings.ToLower(strings.TrimSpace(details))
switch s {
case "bounced", "suppressed":
return models.BounceTypeHard, true
case "failed":
// Infer severity from SMTP-enhanced status if available.
if m := reSMTPStatus.FindStringSubmatch(d); len(m) > 1 {
if strings.HasPrefix(m[1], "5.") {View on GitHub (pinned to 670c01717d)
Solutions
- Confirm the events posted are Azure Communication Services email events where `data` is a JSON object with string fields.
- Validate each array element is a JSON object before posting (or in tests, use a captured real Event Grid envelope).
- Log the raw body and the wrapped json.Unmarshal error to identify which element/field conflicts.
- If testing, use realistic payload samples rather than placeholder strings in the array.
Example fix
// before: array of strings
body := []byte(`["event1","event2"]`)
// after: array of event objects
body := []byte(`[{"eventType":"Microsoft.Communication.EmailDeliveryReportReceived","data":{"recipient":"a@b.com","status":"Bounced"}}]`) Defensive patterns
Strategy: validation
Validate before calling
func hasWellFormedEvents(body []byte) bool {
var evs []struct {
EventType string `json:"eventType"`
Data json.RawMessage `json:"data"`
}
if json.Unmarshal(body, &evs) != nil {
return false
}
for _, e := range evs {
if e.EventType == "" || !json.Valid(e.Data) {
return false
}
var obj map[string]any
if json.Unmarshal(e.Data, &obj) != nil {
return false
}
}
return len(evs) > 0
} Type guard
func isEventObject(raw json.RawMessage) bool {
var ev struct {
EventType string `json:"eventType"`
Data json.RawMessage `json:"data"`
}
if json.Unmarshal(raw, &ev) != nil || ev.EventType == "" {
return false
}
var obj map[string]any
return json.Unmarshal(ev.Data, &obj) == nil
} Try / catch
bounces, err := azure.ProcessBounce(req, body)
if err != nil {
if strings.Contains(err.Error(), "unmarshalling azure event") {
log.Printf("bad event element in Event Grid batch: %v", err)
http.Error(w, "invalid event format", http.StatusBadRequest)
return
}
http.Error(w, "webhook processing failed", http.StatusInternalServerError)
} Prevention
- Pin your Event Grid subscription to expected Azure Communication Services event types and filter others out.
- Test with real captured event envelopes rather than placeholder arrays.
- Return 400 with the per-element error so the sender can diagnose bad elements.
When it happens
Trigger: Calling ProcessSubscription or ProcessBounce with an array containing: raw strings/numbers instead of event objects, an event whose `eventType` is not a string, an event whose `data` is not a JSON object, or corrupt JSON in one element of a batch.
Common situations: Event Grid pushing a different subscription kind (e.g. storage/blob events with differently typed data) to the same endpoint; manual tests with placeholder arrays like `["test"]`; a provider schema update changing field types; binary or truncated bodies from proxy misconfiguration.
Related errors
- error reading validation data: %v
- error unmarshalling azure notification array: %v
- empty event payload
- missing event data
- missing validationCode in subscription payload
AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01).
Data as JSON: /api/errors/cbbbdda936831d6a.
Report an issue: GitHub.