crowdsecurity/crowdsec · error · MarshalFail

event meta '%v': %w: %w

Error message

event meta '%v': %w: %w

What it means

json.Marshal failed while serializing the Meta map of an event attached to an alert being saved to the database. Marshal of a map[string]models.Meta normally only fails for unsupported types (channels, funcs, cyclic structures), so this signals malformed/unsupported payload data in an alert pushed to LAPI. The alert save is aborted with the MarshalFail sentinel.

Source

Thrown at pkg/database/alerts.go:460

	dropped := false

	if len(alertItem.Events) == 0 {
		return nil, nil
	}

	eventBulk := make([]*ent.EventCreate, len(alertItem.Events))

	for i, eventItem := range alertItem.Events {
		ts, err := time.Parse(time.RFC3339, *eventItem.Timestamp)
		if err != nil {
			logger.Errorf("creating alert: Failed to parse event timestamp '%s', defaulting to now: %s", *eventItem.Timestamp, err)

			ts = time.Now().UTC()
		}

		marshallMetas, err := json.Marshal(eventItem.Meta)
		if err != nil {
			return nil, fmt.Errorf("event meta '%v': %w: %w", eventItem.Meta, err, MarshalFail)
		}

		// the serialized field is too big, let's try to progressively strip it
		if event.SerializedValidator(string(marshallMetas)) != nil {
			stripped = true

			valid := false
			stripSize := 2048

			for !valid && stripSize > 0 {
				for _, serializedItem := range eventItem.Meta {
					if len(serializedItem.Value) > stripSize*2 {
						serializedItem.Value = serializedItem.Value[:stripSize] + "<stripped>"
					}
				}

				marshallMetas, err = json.Marshal(eventItem.Meta)
				if err != nil {

View on GitHub (pinned to 909b515798)

Solutions

  1. Inspect the logged '%v' representation of the meta to identify the unencodable value and fix the producer (usually the parser or an LAPI client)
  2. Sanitize event meta before pushing: ensure all keys/values are JSON-safe strings
  3. Add validation in the LAPI client/producer using json.Marshal as a pre-check before sending the alert
  4. If you control the ingestion path, log and drop the offending event instead of failing the whole alert batch

Example fix

// before
alert.Events[0].Meta = models.Meta{Events: map[string][]string{...}} // cyclic/unencodable value
// after
raw, err := json.Marshal(meta)
if err != nil {
    log.Warningf("dropping unencodable event meta: %s", err)
    meta = models.Meta{}
}
Defensive patterns

Strategy: validation

Validate before calling

if _, err := json.Marshal(eventItem.Meta); err != nil {
    // sanitize or drop before pushing to LAPI
}

Try / catch

var marshalErr *database.MarshalFail
if errors.As(err, &marshalErr) {
    log.Errorf("alert rejected: unencodable event meta: %s", err)
}

Prevention

When it happens

Trigger: Inserting an alert (createAlertBatch -> buildEventCreates) whose eventItem.Meta contains values json cannot encode: cyclic references, unsupported types, or invalid UTF-8 keys in the map when marshaled with invalid UTF-8 handling.

Common situations: Custom parsers emitting exotic types into event meta; a parsing pipeline bug producing self-referencing structures; third-party integrations pushing alerts with non-string-safe meta values to LAPI.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/ef70ca5746ba0e08. Report an issue: GitHub.