FiloSottile/age · error
received zero recipient stanzas
Error message
received zero recipient stanzas
What it means
The wrap protocol completed ('done' received) but the plugin returned no recipient-stanza, meaning it produced no wrapped file key. An age file cannot be encrypted without at least one stanza, so the client rejects the result.
Source
Thrown at plugin/client.go:166
return nil, nil, err
}
return nil, nil, fmt.Errorf("%s", s.Body)
case "done":
break ReadLoop
default:
if ok, err := r.ui.handle(r.name, conn, s); err != nil {
return nil, nil, err
} else if !ok {
if err := writeStanza(conn, "unsupported"); err != nil {
return nil, nil, err
}
}
}
}
if len(stanzas) == 0 {
return nil, nil, fmt.Errorf("received zero recipient stanzas")
}
return stanzas, labels, nil
}
type Identity struct {
name string
encoding string
ui *ClientUI
}
var _ age.Identity = &Identity{}
func NewIdentity(s string, ui *ClientUI) (*Identity, error) {
name, _, err := ParseIdentity(s)
if err != nil {
return nil, err
}View on GitHub (pinned to b74dce4cdb)
Solutions
- Upgrade or fix the plugin so it always returns at least one recipient-stanza or an explicit 'error' stanza.
- Verify the recipient is actually supported by that plugin using its CLI.
- Check plugin debug output to see why it produced no stanza.
- Add a non-plugin fallback recipient (e.g. X25519) so encryption can succeed without the plugin.
Example fix
// before (plugin side, buggy)
if !supported(recipient) {
// silently skips, then writes done
}
// after
if !supported(recipient) {
writeStanza(conn, "error", "recipient not supported by this plugin")
return
}
writeStanza(conn, "recipient-stanza", "0", st.Type, st.Args...) Defensive patterns
Strategy: validation
Validate before calling
// Go: confirm the recipient is supported before relying on plugin-only encryption
if !strings.HasPrefix(recipient, "age1yubikey1") {
return fmt.Errorf("recipient not supported by the yubikey plugin")
} Try / catch
if err != nil {
if strings.Contains(err.Error(), "received zero recipient stanzas") {
return fmt.Errorf("plugin produced no output for this recipient; check support or add a fallback recipient: %w", err)
}
return err
} Prevention
- Include a non-plugin fallback recipient in critical files so decryption is never plugin-dependent.
- Verify recipient support with the plugin CLI before programmatic use.
- Fix/upgrade plugins that silently skip recipients instead of sending an error stanza.
- Log plugin transcripts when debugging empty results.
When it happens
Trigger: Calling WrapWithLabels/Wrap with a plugin recipient whose plugin responds 'ok' to stanzas and finishes with 'done' without ever sending a recipient-stanza, e.g. it decided it cannot wrap for the given recipient but failed to send an error stanza.
Common situations: A plugin that silently skips unsupported recipients; a buggy or truncated plugin implementation; a plugin that errored internally but forgot to emit an error stanza; a recipient list the plugin cannot match any identity against.
Related errors
- malformed recipient stanza: unexpected argument count
- malformed recipient stanza: invalid index
- malformed recipient stanza: unexpected index
- repeated labels stanza
- %s
AI-assisted analysis of FiloSottile/age@b74dce4cdb (2026-08-31).
Data as JSON: /api/errors/29615cd2706b8bff.
Report an issue: GitHub.