crowdsecurity/crowdsec · error · ErrUnrecognized
unrecognized syslog message
Error message
unrecognized syslog message
What it means
ErrUnrecognized is returned by Source.parseLine when the incoming syslog line fails BOTH the RFC3164 and RFC5424 parsers. The returned *ParseError carries the raw message plus each parser's individual error so the operator can see why both attempts failed. It means the line is not a recognizable syslog message at all.
Source
Thrown at pkg/acquisition/modules/syslog/run.go:133
if appname != "" {
ret += " " + appname
}
if pid != "" {
ret += "[" + pid + "]: "
} else {
ret += ": "
}
if msg != "" {
ret += msg
}
return ret
}
var ErrUnrecognized = errors.New("unrecognized syslog message")
type ParseError struct {
Reason error
RawMessage []byte
// keep the both attempts for ErrUnrecognized
RFC3164 error
RFC5424 error
}
func (e *ParseError) Error() string {
return e.Reason.Error()
}
func (e *ParseError) Unwrap() error {
return e.Reason
}
func (e *ParseError) Fields() logrus.Fields {View on GitHub (pinned to 909b515798)
Solutions
- Inspect the ParseError fields (raw, rfc3164_err, rfc5424_err) to see exactly why both parsers failed
- Fix the sender's syslog template so it emits valid RFC3164 or RFC5424 format (PRI + timestamp at minimum)
- Set DisableRFCParser: true in the acquisition config if lines are arbitrary payloads with a PRI prefix — only the PRI is stripped
- Verify the sender is targeting the crowdsec syslog datasource port and not sending non-syslog content
Example fix
// before: sender emits raw JSON to syslog port
'{"level":"info","msg":"hi"}' -> ErrUnrecognized
// after: wrap with a PRI, or use raw tail acquisition instead
'<13>Jan 1 00:00:00 host app: {"level":"info","msg":"hi"}'
// or in acquis.yaml:
// source: syslog
// DisableRFCParser: true Defensive patterns
Strategy: try-catch
Validate before calling
// check the line has a plausible PRI before sending to the syslog datasource
func hasPRI(line []byte) bool {
if len(line) < 3 || line[0] != '<' { return false }
end := bytes.IndexByte(line, '>')
if end < 0 || end > 4 { return false }
for _, c := range line[1:end] {
if c < '0' || c > '9' { return false }
}
return true
} Try / catch
var pe *syslog.ParseError
line, err := src.ParseLine(msg)
if err != nil {
if errors.As(err, &pe) && errors.Is(pe, syslog.ErrUnrecognized) {
log.Printf("unrecognized syslog line %q: rfc3164=%v rfc5424=%v",
pe.RawMessage, pe.RFC3164, pe.RFC5424)
}
return
} Prevention
- Keep rsyslog/syslog-ng templates standard so lines are valid RFC3164/5424
- Enable DisableRFCParser only for senders that prefix a PRI to arbitrary payloads
- Send non-syslog logs via file/tail acquisition, not the syslog port
- Inspect ParseError.Fields() ('raw', 'rfc3164_err', 'rfc5424_err') when diagnosing senders
When it happens
Trigger: A UDP/TCP client sends a line to the crowdsec syslog datasource that neither parser accepts — e.g. a bare text line with no PRI, a malformed PRI, garbage bytes, or a truncated RFC5424 header combined with a non-RFC3164 layout.
Common situations: Log forwarders (rsyslog, syslog-ng) configured with a custom/nonstandard template; devices writing JSON or raw app logs directly to the syslog port; binary or partially corrupted datagrams; sending to the wrong port so crowdsec receives unrelated traffic.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- timestamp is not valid
- tag is empty
- pid inside tag must be a number
- pid inside tag must be closed with ']'
- message is empty
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/b633f2e63e9c7b5f.
Report an issue: GitHub.