{"record":{"id":"64e633bd4f691a7a","repo":"FiloSottile/age","slug":"too-much-trailing-whitespace","errorCode":null,"errorMessage":"too much trailing whitespace","messagePattern":"too much trailing whitespace","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"armor/armor.go","lineNumber":126,"sourceCode":"\t\t} else if err != nil && err != io.EOF {\n\t\t\treturn nil, err\n\t\t}\n\t\tline = bytes.TrimSuffix(line, []byte(\"\\n\"))\n\t\tline = bytes.TrimSuffix(line, []byte(\"\\r\"))\n\t\treturn line, nil\n\t}\n\n\tconst maxWhitespace = 1024\n\tdrainTrailing := func() error {\n\t\tbuf, err := io.ReadAll(io.LimitReader(r.r, maxWhitespace))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif len(bytes.TrimSpace(buf)) != 0 {\n\t\t\treturn errors.New(\"trailing data after armored file\")\n\t\t}\n\t\tif len(buf) == maxWhitespace {\n\t\t\treturn errors.New(\"too much trailing whitespace\")\n\t\t}\n\t\treturn io.EOF\n\t}\n\n\tvar removedWhitespace int\n\tfor !r.started {\n\t\tline, err := getLine()\n\t\tif err != nil {\n\t\t\treturn 0, r.setErr(err)\n\t\t}\n\t\t// Ignore leading whitespace.\n\t\tif len(bytes.TrimSpace(line)) == 0 {\n\t\t\tremovedWhitespace += len(line) + 1\n\t\t\tif removedWhitespace > maxWhitespace {\n\t\t\t\treturn 0, r.setErr(errors.New(\"too much leading whitespace\"))\n\t\t\t}\n\t\t\tcontinue\n\t\t}","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/FiloSottile/age/blob/b74dce4cdbe35b5e5f66c06d9612b72f89028758/armor/armor.go#L108-L144","documentation":"drainTrailing is allowed to consume at most maxWhitespace bytes of trailing whitespace after the armor footer. If it fills the limit reader without reaching EOF, the file ends with more whitespace than permitted, so the reader fails with this error to bound memory and reject degenerate inputs.","triggerScenarios":"Reading an armored file that ends with a very large run of whitespace (more than maxWhitespace bytes) after the footer line — e.g. padding added by a script, disk preallocation, or a corrupted file filled with spaces/newlines.","commonSituations":"Logs or payloads padded with trailing newlines/spaces, files produced by buggy tools that append whitespace padding, or streams that keep sending whitespace after the armor ends.","solutions":["Trim the excessive trailing whitespace from the file before decryption.","Fix the upstream producer that appends the whitespace padding.","Stream-process the input to cut it off right after the END footer line."],"exampleFix":"// before: armored file followed by megabytes of newlines\n// after: truncate after footer\nsed -n '/END AGE ENCRYPTED FILE---/q;p' padded.age > clean.age","handlingStrategy":"validation","validationCode":"// Bound trailing whitespace before decrypting\nfunc trimTrailingWS(path string) error {\n    data, err := os.ReadFile(path)\n    if err != nil {\n        return err\n    }\n    return os.WriteFile(path, bytes.TrimRight(data, \" \\t\\r\\n\"), 0o600)\n}","typeGuard":null,"tryCatchPattern":"_, err := io.ReadAll(armor.NewReader(f))\nif err != nil && err.Error() == \"too much trailing whitespace\" {\n    // trim trailing whitespace from the file and retry once\n}","preventionTips":["Avoid padding armored files with whitespace.","Fix producers that append trailing newlines/spaces in loops.","Sanitize inputs before feeding them to armor.NewReader."],"tags":["go","age","armor","reader","whitespace"],"backgroundTag":"excessive-whitespace","analyzedSha":"b74dce4cdbe35b5e5f66c06d9612b72f89028758","analyzedAt":"2026-08-31T23:59:31.627Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}