knadh/listmonk · error

missing event data

Error message

missing event data

What it means

ProcessSubscription unmarshals the first event's RawData and expects a "data" key holding the validation payload. This error is returned when that key is absent from the event data. The library throws it to prevent a nil/missing-data dereference when extracting the validationCode.

Source

Thrown at internal/bounce/webhooks/azure.go:72

// returns the response payload that should be written to HTTP response body.
func (a *Azure) ProcessSubscription(b []byte) (json.RawMessage, error) {
	events, err := parseAzureEvents(b)
	if err != nil {
		return nil, err
	}
	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
}

View on GitHub (pinned to 670c01717d)

Solutions

  1. Ensure the payload sent during subscription registration is an actual SubscriptionValidationEvent whose Data contains validationCode under the expected key.
  2. Inspect events[0].RawData (log it) to see the actual shape and adjust payload construction accordingly.
  3. If using the CloudEvents schema in Event Grid, adjust the webhook or parser to expect the enveloped format.
  4. Add a pre-check that the first event's data exists before calling ProcessSubscription.

Example fix

// before
var payload map[string]json.RawMessage
json.Unmarshal(events[0].RawData, &payload)
res, err := azure.ProcessSubscription(body)
// after
var probe map[string]json.RawMessage
if json.Unmarshal(events[0].RawData, &probe) == nil {
	if _, ok := probe["data"]; !ok {
		// not a subscription validation event; route elsewhere
	}
}
Defensive patterns

Strategy: type-guard

Validate before calling

var probe map[string]json.RawMessage
if err := json.Unmarshal(firstEventRawData, &probe); err != nil || probe["data"] == nil {
	// not a subscription validation payload; route to ProcessBounce instead
}

Type guard

func isValidationEvent(raw json.RawMessage) bool {
	var p map[string]json.RawMessage
	if json.Unmarshal(raw, &p) != nil { return false }
	_, ok := p["data"]
	return ok
}

Try / catch

res, err := azure.ProcessSubscription(body)
if err != nil {
	if strings.Contains(err.Error(), "missing event data") {
		// payload is likely a bounce delivery, not validation: forward to ProcessBounce
		return azure.ProcessBounce(body, req)
	}
	return err
}

Prevention

When it happens

Trigger: The first Azure Event Grid event's Data field does not contain a "data" key — e.g. the event is not a subscription validation event (handshake/data events have different shapes) or the event payload was transformed/stripped in transit.

Common situations: Sending a regular bounce notification event to the subscription-validation code path; an intermediary (API gateway, Event Grid filter/schema like CloudEvents envelope) that renames or nests the data field; testing with handcrafted payloads missing "data".

Related errors


AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01). Data as JSON: /api/errors/50bb2d04b57e3a48. Report an issue: GitHub.