FiloSottile/age · error
malformed confirm stanza: unexpected number of arguments
Error message
malformed confirm stanza: unexpected number of arguments
What it means
In the client's plugin UI handler, a "confirm" stanza from the plugin must carry exactly one or two arguments (the YES option and optionally the NO option, bech32-encoded). A different argument count is rejected as malformed per the age-plugin protocol spec.
Source
Thrown at plugin/client.go:360
if c.DisplayMessage == nil {
return true, writeStanza(conn, "fail")
}
if err := c.DisplayMessage(name, string(s.Body)); err != nil {
return true, writeStanza(conn, "fail")
}
return true, writeStanza(conn, "ok")
case "request-secret", "request-public":
if c.RequestValue == nil {
return true, writeStanza(conn, "fail")
}
secret, err := c.RequestValue(name, string(s.Body), s.Type == "request-secret")
if err != nil {
return true, writeStanza(conn, "fail")
}
return true, writeStanzaWithBody(conn, "ok", []byte(secret))
case "confirm":
if len(s.Args) != 1 && len(s.Args) != 2 {
return true, fmt.Errorf("malformed confirm stanza: unexpected number of arguments")
}
if c.Confirm == nil {
return true, writeStanza(conn, "fail")
}
yes, err := format.DecodeString(s.Args[0])
if err != nil {
return true, fmt.Errorf("malformed confirm stanza: invalid YES option encoding")
}
var no []byte
if len(s.Args) == 2 {
no, err = format.DecodeString(s.Args[1])
if err != nil {
return true, fmt.Errorf("malformed confirm stanza: invalid NO option encoding")
}
}
choseYes, err := c.Confirm(name, string(s.Body), string(yes), string(no))
if err != nil {
return true, writeStanza(conn, "fail")View on GitHub (pinned to b74dce4cdb)
Solutions
- Fix the plugin to send the confirm stanza with exactly one argument (YES) or two (YES and NO), each bech32-encoded
- Update the plugin to a spec-conforming release
- Inspect the plugin's stanza output (enable debugging or run it manually) to see the malformed argument list
Example fix
// before (plugin side)
writeStanzaWithBody(w, "confirm", "yes", "no", "maybe", message)
// after
writeStanzaWithBody(w, "confirm", bech32Encode("yes"), bech32Encode("no"), message) Defensive patterns
Strategy: validation
Validate before calling
// Plugin-side pre-check before emitting confirm
if len(args) < 1 || len(args) > 2 { return errors.New("confirm needs 1 or 2 bech32 args") } Try / catch
if err := unwrapWithPlugin(); err != nil && strings.Contains(err.Error(), "malformed confirm stanza") {
return fmt.Errorf("plugin %s has a broken confirm implementation; upgrade it", pluginName)
} Prevention
- Encode confirm options with bech32 before sending
- Send 1 arg (YES) or 2 args (YES, NO) — never 0 or 3+
- Test interactive plugin flows end-to-end with the official age client
When it happens
Trigger: A plugin calls ui.Confirm with its protocol message built incorrectly — e.g. sending a confirm stanza with zero arguments or three or more — while the client's Unwrap is dispatching stanzas to handle().
Common situations: Custom plugin authors passing empty/extra arguments when emitting the confirm stanza; plugin versions incompatible with the client's protocol implementation.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- malformed confirm stanza: invalid YES option encoding
- malformed confirm stanza: invalid NO option encoding
- malformed file-key stanza: unexpected arguments count
- malformed file-key stanza: invalid index
- malformed file-key stanza: unexpected index
AI-assisted analysis of FiloSottile/age@b74dce4cdb (2026-08-31).
Data as JSON: /api/errors/4910903a8b1b66cb.
Report an issue: GitHub.