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

  1. Ensure at least one age.Recipient is added before calling age.Marshal / Encrypt.
  2. Validate len(recipients) > 0 in caller code and surface a clear error to the user instead of encrypting.
  3. 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

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


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