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

  1. Inspect the ParseError fields (raw, rfc3164_err, rfc5424_err) to see exactly why both parsers failed
  2. Fix the sender's syslog template so it emits valid RFC3164 or RFC5424 format (PRI + timestamp at minimum)
  3. Set DisableRFCParser: true in the acquisition config if lines are arbitrary payloads with a PRI prefix — only the PRI is stripped
  4. 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

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


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