FiloSottile/age · error

too much leading whitespace

Error message

too much leading whitespace

What it means

Before parsing the armor header, the reader skips leading whitespace, but only up to maxWhitespace bytes total. If the file starts with more whitespace than allowed, reading fails with this error, because such input is not a plausibly valid armored file.

Source

Thrown at armor/armor.go:141

			return errors.New("trailing data after armored file")
		}
		if len(buf) == maxWhitespace {
			return errors.New("too much trailing whitespace")
		}
		return io.EOF
	}

	var removedWhitespace int
	for !r.started {
		line, err := getLine()
		if err != nil {
			return 0, r.setErr(err)
		}
		// Ignore leading whitespace.
		if len(bytes.TrimSpace(line)) == 0 {
			removedWhitespace += len(line) + 1
			if removedWhitespace > maxWhitespace {
				return 0, r.setErr(errors.New("too much leading whitespace"))
			}
			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"))
	}

View on GitHub (pinned to b74dce4cdb)

Solutions

  1. Strip the leading whitespace so the file begins with the BEGIN header (e.g. sed/awk from the first '-----BEGIN' line).
  2. Fix the tool or script emitting the whitespace preamble.
  3. Regenerate the armored file directly with the age CLI without a preamble.

Example fix

// before
cat preamble.txt armor.age > combined.age
// after
awk '/-----BEGIN AGE ENCRYPTED FILE-----/{f=1} f' combined.age > armor.age
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the stream starts with the armor header before decrypting
func skipLeadingBlankLines(r io.Reader) (io.Reader, error) {
    br := bufio.NewReader(r)
    for {
        line, err := br.ReadString('\n')
        if err != nil {
            return nil, err
        }
        if strings.TrimSpace(line) != "" {
            return io.MultiReader(strings.NewReader(line), br), nil
        }
    }
}

Type guard

func isArmorHeader(line string) bool {
    return strings.TrimSpace(line) == "-----BEGIN AGE ENCRYPTED FILE-----"
}

Try / catch

out, err := io.ReadAll(armor.NewReader(f))
if err != nil && err.Error() == "too much leading whitespace" {
    // strip leading blank lines and retry
}

Prevention

When it happens

Trigger: Calling Read (or age.Decrypt) on an armored stream that begins with more than maxWhitespace bytes of blank lines, spaces, tabs, or CR/LF before the '-----BEGIN AGE ENCRYPTED FILE-----' header.

Common situations: Email or chat pastes with many leading blank lines, concatenated text files where the armor begins after a large preamble, or templates/heredocs emitting excessive blank lines before the payload.

Related errors


AI-assisted analysis of FiloSottile/age@b74dce4cdb (2026-08-31). Data as JSON: /api/errors/e6867be73d8aadf4. Report an issue: GitHub.