crowdsecurity/crowdsec · warning
polling papi message format is not compatible: %+v: %w
Error message
polling papi message format is not compatible: %+v: %w
What it means
The PAPI long-poll loop received an event whose payload could not be JSON-unmarshaled into the internal Message structure, so the order (decision/alert/management change) is dropped. The server logs and skips this message rather than crashing, since subsequent poll iterations will continue. This guards against incompatible or truncated payloads from the polling endpoint.
Source
Thrown at pkg/apiserver/papi.go:135
pullTomb: tomb.Tomb{},
syncTomb: tomb.Tomb{},
apiClient: apic.apiClient,
apic: apic,
consoleConfig: consoleConfig,
Logger: logger.WithFields(log.Fields{"interval": SyncInterval.Seconds(), "source": "papi"}),
stopChan: make(chan struct{}),
}
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)View on GitHub (pinned to 909b515798)
Solutions
- Look at the logged '%+v' payload in the error to see what was actually received.
- Verify api.client.papi_url points at the official CAPI PAPI endpoint (…/v1/decisions/stream/poll path is set automatically by NewPAPI).
- Check for intercepting proxies / corporate TLS inspection altering the response; bypass or fix them.
- Upgrade crowdsec — a schema change from CAPI usually requires a matching client release.
- Restart crowdsec to re-authenticate and get a clean session if the endpoint is returning error pages.
Defensive patterns
Strategy: try-catch
Validate before calling
var probe map[string]any
if err := json.Unmarshal(raw, &probe); err != nil {
// payload isn't JSON at all — likely a proxy/error page; alert before feeding to consumers
} Try / catch
if err := p.handleEvent(ctx, event, sync); err != nil {
var ute *json.UnmarshalTypeError
if errors.As(err, &ute) {
logger.WithField("data", event.Data).Warn("PAPI message schema mismatch — check crowdsec/CAPI versions")
}
// continue polling; single bad message must not kill the loop
continue
} Prevention
- Keep crowdsec up to date so the Message schema matches current CAPI.
- Ensure no TLS-intercepting proxy or captive portal rewrites responses on the CAPI endpoint.
- Alert on repeated occurrences — one bad message is noise, a stream of them is a version/proxy problem.
- Log the raw event payload at debug level during incidents to capture the incompatible format.
When it happens
Trigger: json.Unmarshal([]byte(event.Data), message) fails inside handleEvent — the long-poll response body is not valid JSON or does not match the Message schema (missing/renamed fields, HTML error page instead of JSON, wrong endpoint version).
Common situations: A proxy/Captive portal or the CDN returning an HTML error page on the poll URL; CAPI API version drift where the message schema changed; a misconfigured papi_url pointing at a non-PAPI endpoint; corrupted gzip/proxy encoding mangling the body.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- no header in message, skipping
- no source user in header message, skipping
- operation '%s' unknown, continue
- failed to get response: %w
- failed to decode response: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/5c7d397eff1b4a79.
Report an issue: GitHub.