FiloSottile/age · error
column limit exceeded
Error message
column limit exceeded
What it means
Armor lines are restricted to format.ColumnsPerLine (64) characters, matching the encoder's output. A longer line means the data was not produced by this armor format (or was reformatted), so the reader rejects it instead of guessing how to split it.
Solutions
- Re-wrap body lines to at most 64 columns (e.g. fold -w 64) and retry decryption.
- Re-obtain the armored file from its original source or re-run the age CLI to produce correctly wrapped armor.
- Disable editor word-wrap and avoid MIME re-encoding when transferring .age files.
Example fix
// before: one 200-char base64 line in the armor body // after fold -w 64 longline.age > wrapped.age
Defensive patterns
Strategy: validation
Validate before calling
// Check armor line widths before decrypting
func checkLineLengths(data []byte) error {
for _, l := range bytes.Split(data, []byte('\n')) {
l = bytes.TrimRight(l, "\r")
if !bytes.HasPrefix(l, []byte("-----")) && len(l) > 64 {
return fmt.Errorf("line too long: %d", len(l))
}
}
return nil
} Type guard
func isWrappedArmorLine(line []byte) bool {
return len(line) <= 64
} Try / catch
_, err := io.ReadAll(armor.NewReader(f))
if err != nil && err.Error() == "column limit exceeded" {
// re-wrap lines with fold -w 64 or re-export the armor
} Prevention
- Keep armor lines at the encoder's 64-column width.
- Do not paste base64 from MIME emails (76-char lines) into age armor.
- Disable word-wrap when editing armored files.
When it happens
Trigger: Reading an armored file where a body line exceeds 64 characters — e.g. armor reflowed by a text editor with a different wrap width, MIME base64 from email (76-char lines) pasted into an age armor envelope, or hand-concatenated base64 lines.
Common situations: Extracting base64 from a MIME email attachment into an age armor template, editors with word-wrap rewriting the file, or scripts joining base64 lines into one long line.
Related errors
- empty line in armored data
- too much leading whitespace
- too much trailing whitespace
- trailing data after armored file
- unexpected newline character
AI-assisted analysis of FiloSottile/age@b74dce4cdb (2026-08-31).
Data as JSON: /api/errors/fd39c917730b0b06.
Report an issue: GitHub.
Appendix: source
Thrown at armor/armor.go:161
continue
}
if string(line) != Header {
return 0, r.setErr(fmt.Errorf("invalid first line: %q", line))
}
r.started = true
}
line, err := getLine()
if err != nil {
return 0, r.setErr(err)
}
if string(line) == Footer {
return 0, r.setErr(drainTrailing())
}
if len(line) == 0 {
return 0, r.setErr(errors.New("empty line in armored data"))
}
if len(line) > format.ColumnsPerLine {
return 0, r.setErr(errors.New("column limit exceeded"))
}
// Reject newline characters ignored by base64.Decode.
if bytes.ContainsAny(line, "\n\r") {
return 0, r.setErr(errors.New("unexpected newline character"))
}
r.unread = r.buf[:]
n, err := base64.StdEncoding.Strict().Decode(r.unread, line)
if err != nil {
return 0, r.setErr(err)
}
r.unread = r.unread[:n]
if n < format.BytesPerLine {
line, err := getLine()
if err != nil {
return 0, r.setErr(err)
}
if string(line) != Footer {View on GitHub (pinned to b74dce4cdb)