crowdsecurity/crowdsec · error
PRI must be a number
Error message
PRI must be a number
What it means
parsePRI reads the syslog PRI field between '<' and '>'. Each character inside the brackets must be a decimal digit; if any character before the closing '>' is not '0'-'9', the parser rejects the line because PRI is defined by RFC 5424 as a numeric priority value. This indicates the line is not a well-formed RFC 5424 syslog message.
Source
Thrown at pkg/acquisition/modules/syslog/internal/parser/rfc5424/parse.go:59
}
func (r *RFC5424) parsePRI() error {
pri := 0
if r.buf[r.position] != '<' {
return errors.New("PRI must start with '<'")
}
r.position++
for r.position < r.len {
c := r.buf[r.position]
if c == '>' {
r.position++
break
}
if c < '0' || c > '9' {
return errors.New("PRI must be a number")
}
pri = pri*10 + int(c-'0')
r.position++
}
if pri > 999 {
return errors.New("PRI must be up to 3 characters long")
}
if r.position == r.len && r.buf[r.position-1] != '>' {
return errors.New("PRI must end with '>'")
}
r.PRI = pri
return nil
}
func (r *RFC5424) parseVersion() error {View on GitHub (pinned to 909b515798)
Solutions
- Verify the sender actually emits RFC 5424 format: the message must begin "<PRI>VERSION ..."; use a different parser/decoder for RFC 3164 lines.
- Inspect the raw line (log the buffer before Parse) to find what non-numeric character follows the '<'.
- Check network path (UDP vs TCP framing) for truncation or interleaved data corrupting the message start.
Example fix
// before
parser.Parse([]byte("<34 Notice>1 2024-01-01T00:00:00Z host app 1 - msg"))
// after (PRI must be purely numeric)
parser.Parse([]byte("<34>1 2024-01-01T00:00:00Z host app 1 - msg")) Defensive patterns
Strategy: validation
Validate before calling
// Go: check the PRI is '<' followed by digits and '>' before parsing
func looksLikePRI(line []byte) bool {
if len(line) < 3 || line[0] != '<' {
return false
}
i := 1
for i < len(line) && line[i] != '>' {
if line[i] < '0' || line[i] > '9' {
return false
}
i++
}
return i < len(line) && line[i] == '>' && i <= 4
} Try / catch
if err := parser.Parse(line); err != nil {
if strings.Contains(err.Error(), "PRI must be a number") {
// route to legacy/rfc3164 parser or drop to deadletter
}
} Prevention
- Pre-validate the line starts with '<digits>' before calling Parse
- Confirm senders use RFC 5424 format, not RFC 3164
- Log raw malformed lines for diagnosis instead of silently dropping them
When it happens
Trigger: Calling RFC5424.Parse on a line like "<12ab>1 ..." or "<PR>1 ..." where a non-digit character appears between '<' and '>'. Also fired when PRI exceeds 3 digits and the 4th character is not '>' (e.g. "<12345..." hits '4', a digit, then later overflow check applies; but "<12x4>" hits 'x' immediately).
Common situations: A syslog sender emitting RFC 3164 (legacy) lines, non-syslog garbage on the socket, a relay mangling the header, or UDP datagram fragmentation/interleaving corrupting the message start.
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
- PRI must start with '<'
- pid inside tag must be closed with ']'
- PRI must be up to 3 characters long
- PRI must end with '>'
- version must be 1
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/6da000853a796515.
Report an issue: GitHub.