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

  1. Upgrade or fix the plugin so it always returns at least one recipient-stanza or an explicit 'error' stanza.
  2. Verify the recipient is actually supported by that plugin using its CLI.
  3. Check plugin debug output to see why it produced no stanza.
  4. 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

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


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