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
- Upgrade or fix the sending side to include the source user in every message header
- Check sender version compatibility with the receiving CrowdSec version
- 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
- Populate Source on every header in the sender
- Add a sender-side unit test asserting non-nil header and source
- Check for version drift between peers after upgrades
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
- no header in message, skipping
- polling papi message format is not compatible: %+v: %w
- operation '%s' unknown, continue
- failed to decode response: %w
- message for '%s' contains bad data format: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/b7592b9b0cb51432.
Report an issue: GitHub.