FiloSottile/age · error

failed to compute stream overhead: %w

Error message

failed to compute stream overhead: %w

What it means

Inspect computes the streaming overhead (nonce + chunk frames) from the encrypted payload size via streamOverhead, which calls stream.PlaintextSize. If the payload is smaller than the 16-byte stream nonce or the size is inconsistent with STREAM framing, this error is returned wrapped.

Source

Thrown at internal/inspect/inspect.go:94

	// (which can have LF or CRLF line endings, varying its size), read to
	// the end to determine it.
	if fileSize == -1 || data.Armor {
		n, err := io.Copy(io.Discard, rest)
		if err != nil {
			return nil, fmt.Errorf("failed to read rest of file: %w", err)
		}
		fileSize = data.Sizes.Header + n
		if !tr.done {
			panic("trackReader not done after io.Copy")
		}
		if tr.count != fileSize && !data.Armor {
			panic("trackReader count mismatch")
		}
		data.Sizes.Armor = tr.count - fileSize
	}
	data.Sizes.Overhead, err = streamOverhead(fileSize - data.Sizes.Header)
	if err != nil {
		return nil, fmt.Errorf("failed to compute stream overhead: %w", err)
	}
	data.Sizes.MinPayload = fileSize - data.Sizes.Header - data.Sizes.Overhead
	data.Sizes.MaxPayload = data.Sizes.MinPayload
	return data, nil
}

type trackReader struct {
	r     io.Reader
	count int64
	done  bool
}

func (tr *trackReader) Read(p []byte) (int, error) {
	if tr.done {
		return 0, io.EOF
	}
	n, err := tr.r.Read(p)
	tr.count += int64(n)

View on GitHub (pinned to b74dce4cdb)

Solutions

  1. Verify the file is complete and its declared size is correct
  2. Re-transfer the file; a payload smaller than 16 bytes cannot be a valid age payload
  3. Double-check the fileSize argument passed to Inspect (use the real file size; -1 to auto-detect)
  4. Confirm the file was produced by age and not another tool

Example fix

// before
inspect.Inspect(f, size) // size miscounted from armor
// after
st, _ := f.Stat()
inspect.Inspect(f, st.Size()) // let Inspect detect armor and size itself
Defensive patterns

Strategy: validation

Validate before calling

st, _ := f.Stat()
hdrOverhead := int64(200) // generous minimum header size
if st.Size() < hdrOverhead+16 { return fmt.Errorf("file too small to contain a valid age payload") }

Type guard

n/a — stream.PlaintextSize returns an error rather than a type mismatch; check it with errors.Is

Try / catch

data, err := inspect.Inspect(f, size)
if err != nil {
    if strings.Contains(err.Error(), "stream overhead") { return fmt.Errorf("payload size inconsistent with age STREAM framing") }
    return err
}

Prevention

When it happens

Trigger: inspect.Inspect calls streamOverhead(fileSize - data.Sizes.Header) and either payloadSize < 16 or stream.PlaintextSize rejects the encrypted size (e.g., size not congruent with chunk + 16-byte tag framing).

Common situations: Inspecting truncated or corrupted age files; files that are shorter than a single chunk plus nonce; non-age data that got past the header by coincidence; arithmetic on wrong fileSize values passed by the caller.

Related errors


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