FiloSottile/age · error
expected unsupported stanza, got %q
Error message
expected unsupported stanza, got %q
What it means
This error is thrown by the plugin's test/protocol helper expectUnsupported when, after sending an unsupported-recipient command, the plugin reads back a stanza whose Type is not "unsupported". It indicates the v1 plugin protocol handshake deviated from the expected sequence: the counterpart responded with a different stanza type than the required "unsupported" acknowledgment.
Source
Thrown at plugin/plugin.go:664
case "fail":
if err := expectStanzaWithNoBody(s, 0); err != nil {
return nil, fmt.Errorf("%v", err)
}
return s, nil
case "ok":
return s, nil
default:
return nil, fmt.Errorf("expected ok or fail stanza, got %q", s.Type)
}
}
func expectUnsupported(sr *format.StanzaReader) error {
unsupported, err := sr.ReadStanza()
if err != nil {
return fmt.Errorf("failed to read unsupported stanza: %v", err)
}
if unsupported.Type != "unsupported" {
return fmt.Errorf("expected unsupported stanza, got %q", unsupported.Type)
}
return expectStanzaWithNoBody(unsupported, 0)
}
func (p *Plugin) writeError(args []string, err error) error {
s := &format.Stanza{Type: "error", Args: args}
s.Body = []byte(err.Error())
if err := s.Marshal(p.stdout); err != nil {
return fmt.Errorf("failed to write error stanza: %v", err)
}
if err := expectOk(p.sr); err != nil {
return fmt.Errorf("%v", err)
}
return nil
}
View on GitHub (pinned to b74dce4cdb)
Solutions
- Inspect the %q value in the message to see which stanza type was actually received and trace who emitted it.
- Verify the client/peer implements the age plugin protocol's unsupported-stanza acknowledgment correctly.
- Confirm the order of stanzas written before calling expectUnsupported matches the protocol spec.
- If you added custom stanzas, ensure unsupported recipients still produce a Type "unsupported" stanza.
Example fix
// before
s := &format.Stanza{Type: "ack"}
// after
s := &format.Stanza{Type: "unsupported"} Defensive patterns
Strategy: validation
Validate before calling
if st, ok := stanza.(*format.Stanza); !ok || st.Type != "unsupported" {
return fmt.Errorf("peer did not send unsupported stanza, got %v", st)
} Prevention
- Follow the age plugin protocol stanza ordering exactly when implementing clients.
- Log every stanza type sent and received during plugin handshakes.
- Test against the reference plugin implementation before deploying custom peers.
When it happens
Trigger: Calling Plugin.RecipientV1 or Plugin.IdentityV1 in a mode that exercises the unsupported-stanza path while the StanzaReader returns a stanza with a Type other than "unsupported" (e.g. an "ok", "error", or body-carrying stanza).
Common situations: Custom or third-party age plugin clients that emit a wrong acknowledgement stanza; protocol-level regressions after changing the plugin message flow; a peer replying with an error stanza where an unsupported ack was expected.
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/8a7857dfff89937c.
Report an issue: GitHub.