FiloSottile/age · error
recipient encodings not supported
Error message
recipient encodings not supported
What it means
RecipientV1 returns this when the plugin's Recipient field is nil, meaning the plugin binary does not implement a recipient-v1 encoding at all. The client sent recipient stanza(s), but this plugin was only built for identities (or nothing). The library cannot wrap the file key, so it fails fast with a per-recipient error naming the offending recipient index.
Source
Thrown at plugin/plugin.go:252
if len(recipientStrings)+len(identityStrings) == 0 {
return p.fatalf("no recipients or identities provided")
}
if len(fileKeys) == 0 {
return p.fatalf("no file keys provided")
}
var recipients, identities []age.Recipient
for i, s := range recipientStrings {
name, data, err := ParseRecipient(s)
if err != nil {
return p.recipientError(i, err)
}
if name != p.name {
return p.recipientError(i, fmt.Errorf("unsupported plugin name: %q", name))
}
if p.recipient == nil {
return p.recipientError(i, fmt.Errorf("recipient encodings not supported"))
}
r, err := p.recipient(data)
if err != nil {
return p.recipientError(i, err)
}
recipients = append(recipients, r)
}
for i, s := range identityStrings {
name, data, err := ParseIdentity(s)
if err != nil {
return p.identityError(i, err)
}
if name != p.name {
return p.identityError(i, fmt.Errorf("unsupported plugin name: %q", name))
}
if p.idAsRecipient == nil {
return p.identityError(i, fmt.Errorf("identity encodings not supported"))
}View on GitHub (pinned to b74dce4cdb)
Solutions
- Set the Plugin.Recipient callback in the plugin's main before calling RecipientV1
- Make the plugin's flag handling reject recipient mode when no Recipient encoding is implemented, with a clear usage message
- Update the plugin to a version that supports recipient encodings
Example fix
// before
p := plugin.New(name, nil, nil)
os.Exit(p.RecipientV1(os.Stdin, os.Stdout, os.Args...))
// after
p := plugin.New(name, func(data []byte) (age.Recipient, error) { return parseRecipient(data) }, nil)
os.Exit(p.RecipientV1(os.Stdin, os.Stdout, os.Args...)) Defensive patterns
Strategy: validation
Validate before calling
// In the plugin's main, before RecipientV1:
if p == nil || p.Recipient == nil {
fmt.Fprintf(os.Stderr, "usage: %s does not support recipient encodings\n", os.Args[0])
os.Exit(1)
}
// In the age client/integration, before invoking:
// out, _ := exec.Command(pluginPath, "--age-plugin=plugin-v1").Output(); strings.Contains(string(out), "recipient-v1") Prevention
- Always wire Plugin.Recipient when building a recipient-capable plugin
- Probe the plugin binary with --age-plugin=plugin-v1 to see which modes it supports
- Test plugin main flags before shipping
When it happens
Trigger: Running the plugin binary in RecipientV1 mode while the Plugin was constructed without setting Plugin.Recipient; e.g. an age-plugin binary compiled from a main that only registers Identity and calls RecipientV1 as part of generic dispatch.
Common situations: A plugin supporting only identity decryption (e.g. a hardware-token plugin) is passed as a -r recipient argument; a plugin refactor renamed the callback and left Recipient nil; wiring the wrong constructor so Recipient was never assigned.
Related errors
- identity encodings not supported
- %s plugin: %w
- couldn't start plugin: %w
- malformed recipient stanza: unexpected argument count
- malformed recipient stanza: invalid index
AI-assisted analysis of FiloSottile/age@b74dce4cdb (2026-08-31).
Data as JSON: /api/errors/f626fd38e06d8a08.
Report an issue: GitHub.