FiloSottile/age · error
no recipient stanzas
Error message
no recipient stanzas
What it means
MarshalWithoutMAC refuses to serialize a Header that has no recipient stanzas. An age file header must contain at least one recipient stanza wrapping the file key; writing a header with zero recipients would produce a structurally invalid file no implementation can decrypt. It is thrown as a guard before the intro line is written.
Source
Thrown at internal/format/format.go:147
}
}
if _, err := io.WriteString(w, "\n"); err != nil {
return err
}
ww := NewWrappedBase64Encoder(b64, w)
if _, err := ww.Write(r.Body); err != nil {
return err
}
if err := ww.Close(); err != nil {
return err
}
_, err := io.WriteString(w, "\n")
return err
}
func (h *Header) MarshalWithoutMAC(w io.Writer) error {
if len(h.Recipients) == 0 {
return errors.New("no recipient stanzas")
}
if _, err := io.WriteString(w, intro); err != nil {
return err
}
for _, r := range h.Recipients {
if err := r.Marshal(w); err != nil {
return err
}
}
_, err := fmt.Fprintf(w, "%s", footerPrefix)
return err
}
func (h *Header) Marshal(w io.Writer) error {
if err := h.MarshalWithoutMAC(w); err != nil {
return err
}
mac := b64.EncodeToString(h.MAC)View on GitHub (pinned to b74dce4cdb)
Solutions
- Ensure at least one age.Recipient is added before calling age.Marshal / Encrypt.
- Validate len(recipients) > 0 in caller code and surface a clear error to the user instead of encrypting.
- If recipients come from parsed input, check the parse produced at least one entry and reject empty input up front.
Example fix
// before
if err := age.Encrypt(out, recipients...); ... // recipients empty
// after
if len(recipients) == 0 {
return errors.New("no recipients specified")
}
w, err := age.Encrypt(out, recipients...) Defensive patterns
Strategy: validation
Validate before calling
if len(recipients) == 0 {
return errors.New("at least one recipient is required")
}
w, err := age.Encrypt(out, recipients...) Try / catch
if err != nil {
if err.Error() == "no recipient stanzas" {
return errors.New("encrypt: no recipients configured")
}
return err
} Prevention
- Always build the recipient list explicitly and assert non-empty before Encrypt.
- Fail fast at config-load time if no recipients are configured.
- Unit-test the empty-recipient code path.
When it happens
Trigger: Calling age.Marshal (or headerMAC, which calls MarshalWithoutMAC) with a Recipients list of length zero — e.g. age Encrypt with no Recipient arguments.
Common situations: Building recipients programmatically from user input or config where an empty list slips through; piping recipients parsed from a file that turned out empty; forgetting to add any recipient before Encrypt.
Related errors
- SSH public key is not an RSA key
- failed to decrypt and authenticate payload chunk, file may b
- invalid HRP: %q
- invalid HRP character: hrp[%d]=%d
- mixed case HRP: %q
AI-assisted analysis of FiloSottile/age@b74dce4cdb (2026-08-31).
Data as JSON: /api/errors/e71b6156f521eea1.
Report an issue: GitHub.