FiloSottile/age · error
%s
Error message
%s
What it means
The plugin sent an 'error' stanza, indicating it failed on its side during the wrap protocol. The client surfaces the plugin's error body verbatim as the returned error, so this is the plugin's own failure message (device error, permission denial, unsupported recipient, etc.).
Source
Thrown at plugin/client.go:151
if err := writeStanza(conn, "ok"); err != nil {
return nil, nil, err
}
case "labels":
if labels != nil {
return nil, nil, fmt.Errorf("repeated labels stanza")
}
labels = s.Args
if err := writeStanza(conn, "ok"); err != nil {
return nil, nil, err
}
case "error":
if err := writeStanza(conn, "ok"); err != nil {
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, nilView on GitHub (pinned to b74dce4cdb)
Solutions
- Read the error body text (it is the plugin's message) and act on it directly.
- Verify the hardware/agent the plugin depends on is available and unlocked.
- Validate the recipient string format for that plugin using its own tooling.
- Update the plugin; if the message is an internal error, reproduce it with the plugin CLI and report upstream.
Example fix
// before
out, err := age.Wrap(...) // returns plugin body e.g. "yubikey: device not found"
// after
out, err := age.Wrap(...)
if err != nil {
if strings.Contains(err.Error(), "device not found") {
return fmt.Errorf("plug in the YubiKey and retry: %w", err)
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go: pre-check the device/agent the plugin depends on when possible // e.g. run the plugin's own list/status command to verify the key is reachable
Try / catch
stanzas, labels, err := client.WrapWithLabels(fileKey)
if err != nil {
body := strings.TrimSpace(err.Error()) // plugin's own error text
if strings.Contains(body, "device not found") || strings.Contains(body, "PIN") {
return fmt.Errorf("unlock/present the hardware token: %s", body)
}
return fmt.Errorf("plugin reported: %s", body)
} Prevention
- Surface plugin error bodies verbatim to users; they describe the plugin-side cause.
- Ensure hardware tokens/agents are available and unlocked before encrypting.
- Validate recipient formats with the plugin's own CLI before programmatic use.
- Keep plugins updated; internal plugin errors are often fixed upstream.
When it happens
Trigger: Calling WrapWithLabels/Wrap when the plugin starts successfully but responds with an 'error' stanza, e.g. a YubiKey plugin cannot reach the key, the smartcard is locked, or the recipient is unsupported by the plugin.
Common situations: Hardware token not present or locked (PIN retries exhausted); touch/agent confirmation required but not granted; plugin does not recognize the recipient string; plugin-side internal errors.
Related errors
- malformed recipient stanza: unexpected argument count
- malformed recipient stanza: invalid index
- malformed recipient stanza: unexpected index
- repeated labels stanza
- received zero recipient stanzas
AI-assisted analysis of FiloSottile/age@b74dce4cdb (2026-08-31).
Data as JSON: /api/errors/bd9aa8e377b8a948.
Report an issue: GitHub.