{"record":{"id":"92aada3b1f100979","repo":"crowdsecurity/crowdsec","slug":"version-must-be-followed-by-a-space","errorCode":null,"errorMessage":"version must be followed by a space","messagePattern":"version must be followed by a space","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/acquisition/modules/syslog/internal/parser/rfc5424/parse.go","lineNumber":83,"sourceCode":"\tif pri > 999 {\n\t\treturn errors.New(\"PRI must be up to 3 characters long\")\n\t}\n\n\tif r.position == r.len && r.buf[r.position-1] != '>' {\n\t\treturn errors.New(\"PRI must end with '>'\")\n\t}\n\n\tr.PRI = pri\n\treturn nil\n}\n\nfunc (r *RFC5424) parseVersion() error {\n\tif r.buf[r.position] != '1' {\n\t\treturn errors.New(\"version must be 1\")\n\t}\n\tr.position += 2\n\tif r.position >= r.len {\n\t\treturn errors.New(\"version must be followed by a space\")\n\t}\n\treturn nil\n}\n\nfunc (r *RFC5424) parseTimestamp() error {\n\ttimestamp := []byte{}\n\n\tif r.buf[r.position] == NIL_VALUE {\n\t\tr.Timestamp = time.Now().UTC().Round(0)\n\t\tr.position += 2\n\t\treturn nil\n\t}\n\n\tfor r.position < r.len {\n\t\tc := r.buf[r.position]\n\t\tif c == ' ' {\n\t\t\tbreak\n\t\t}","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/acquisition/modules/syslog/internal/parser/rfc5424/parse.go#L65-L101","documentation":"After checking the version digit, parseVersion advances the position by 2 (version char + the following space) and verifies the buffer still has data. If the line ends right after the version character, there is no space/timestamp following and the parser reports the missing separator.","triggerScenarios":"Calling RFC5424.Parse on a message that ends after \"<34>1\", e.g. \"<34>1\" or \"<34>1\\n\" — after position += 2, position >= r.len.","commonSituations":"A truncated syslog frame from a TCP stream split mid-header, an empty-ish test message, or a device emitting only the header when it has nothing to log.","solutions":["Ensure complete frames reach the parser: for TCP syslog use octet counting so partial reads are not parsed.","Check the sender isn't emitting empty/truncated messages.","Log the raw incomplete line and trace which source/framing produces it."],"exampleFix":"// before (line ends after version)\nparser.Parse([]byte(\"<34>1\"))\n// after (version followed by space and timestamp)\nparser.Parse([]byte(\"<34>1 2024-01-01T00:00:00Z host app 1 - msg\"))","handlingStrategy":"validation","validationCode":"// Go: require more than '<PRI>1' before parsing\nfunc hasHeaderTail(line []byte) bool {\n\ti := bytes.IndexByte(line, '>')\n\treturn i > 0 && len(line) > i+3 && line[i+1] == '1' && line[i+2] == ' '\n}","typeGuard":null,"tryCatchPattern":"if err := parser.Parse(line); err != nil {\n\tif strings.Contains(err.Error(), \"followed by a space\") {\n\t\t// hold the fragment and wait for the rest of the frame\n\t}\n}","preventionTips":["Use framing that guarantees complete messages (octet counting)","Reject or buffer messages shorter than the minimum header '<P>1 '","Monitor senders emitting empty/truncated frames"],"tags":["syslog","rfc5424","parsing","truncated-message"],"backgroundTag":"invalid-argument-format","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}