crowdsecurity/crowdsec · warning

no source user in header message, skipping

Error message

no source user in header message, skipping

What it means

A polled message has a Header but its Source field is nil, i.e. the header does not identify which user/service sent it. Since the operation handlers need the source identity, the message is rejected and skipped with this error.

Source

Thrown at pkg/apiserver/papi.go:143

	return papi, nil
}

func (p *Papi) handleEvent(ctx context.Context, event longpollclient.Event, sync bool) error {
	logger := p.Logger.WithField("request-id", event.RequestId)
	logger.Debugf("message received: %+v", event.Data)

	message := &Message{}
	if err := json.Unmarshal([]byte(event.Data), message); err != nil {
		return fmt.Errorf("polling papi message format is not compatible: %+v: %w", event.Data, err)
	}

	if message.Header == nil {
		return errors.New("no header in message, skipping")
	}

	if message.Header.Source == nil {
		return errors.New("no source user in header message, skipping")
	}

	operationFunc, ok := operationMap[message.Header.OperationType]
	if !ok {
		return fmt.Errorf("operation '%s' unknown, continue", message.Header.OperationType)
	}

	metrics.PapiOrdersReceived.WithLabelValues(message.Header.OperationType, message.Header.OperationCmd).Inc()

	logger.Debugf("Calling operation '%s'", message.Header.OperationType)

	err := operationFunc(ctx, message, p, sync)
	if err != nil {
		return fmt.Errorf("'%s %s failed: %w", message.Header.OperationType, message.Header.OperationCmd, err)
	}

	return nil
}

View on GitHub (pinned to 909b515798)

Solutions

  1. Upgrade or fix the sending side to include the source user in every message header
  2. Check sender version compatibility with the receiving CrowdSec version
  3. Validate the message format with a sample payload before publishing

Example fix

// before (sender)
msg := Message{Header: &Header{OperationType: op}}
// after
msg := Message{Header: &Header{OperationType: op, Source: &User{ID: srcID}}}
Defensive patterns

Strategy: try-catch

Validate before calling

if msg.Header != nil && msg.Header.Source == nil {
    return errors.New("header missing source user")
}

Type guard

func hasSource(m *Message) bool {
    return m != nil && m.Header != nil && m.Header.Source != nil
}

Try / catch

if err := p.handleEvent(ctx, event); err != nil {
    log.WithError(err).Debug("skipping message")
    continue
}

Prevention

When it happens

Trigger: PullOnce/Pull -> handleEvent when message.Header != nil but message.Header.Source == nil in the unmarshaled papi message.

Common situations: Sender built the header without populating source; older sender version predating the Source field; hand-crafted or test messages posted to the channel.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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