FiloSottile/age · error
malformed file-key stanza: unexpected arguments count
Error message
malformed file-key stanza: unexpected arguments count
What it means
During age plugin unwrapping, the client parses a 'file-key' stanza sent by the plugin binary. This error means the stanza carried a number of arguments other than exactly one (the file-key index). The age plugin protocol v1 requires the file-key stanza to have exactly one argument, so the client rejects anything else as a protocol violation.
Source
Thrown at plugin/client.go:270
}
}
if err := writeStanza(conn, "done"); err != nil {
return nil, err
}
// Phase 2: plugin responds with various commands and a file key
sr := format.NewStanzaReader(bufio.NewReader(conn))
ReadLoop:
for {
s, err := i.ui.readStanza(i.name, sr)
if err != nil {
return nil, err
}
switch s.Type {
case "file-key":
if len(s.Args) != 1 {
return nil, fmt.Errorf("malformed file-key stanza: unexpected arguments count")
}
n, err := strconv.Atoi(s.Args[0])
if err != nil {
return nil, fmt.Errorf("malformed file-key stanza: invalid index")
}
// We only send a single file key, so the index must be 0.
if n != 0 {
return nil, fmt.Errorf("malformed file-key stanza: unexpected index")
}
if fileKey != nil {
return nil, fmt.Errorf("received duplicated file-key stanza")
}
fileKey = s.Body
if err := writeStanza(conn, "ok"); err != nil {
return nil, err
}View on GitHub (pinned to b74dce4cdb)
Solutions
- Update the plugin binary to a version that conforms to the age-plugin protocol v1 (exactly one argument in the file-key stanza)
- Check which plugin binary is being resolved for AGE-PLUGIN-<name>-1 identities (age-plugin-<name> on PATH / testOnlyPluginPath) and remove shadowing scripts
- If you wrote the plugin, fix its Unwrap loop to send writeStanza(w, "file-key", "0") with a single argument
- Verify the recipient/identity stanza name matches the plugin actually handling it; a mismatched plugin may answer with stanzas it shouldn't
Example fix
// before (plugin side) writeStanza(w, "file-key", "0", "extra") // after writeStanza(w, "file-key", "0")
Defensive patterns
Strategy: validation
Validate before calling
// Client can't pre-validate plugin output; validate the plugin before use.
out, err := exec.Command("age-plugin-foo", "--age-plugin=recipient-v1").Output()
if err != nil { log.Fatalf("plugin broken: %v", err) } Try / catch
if _, err := identity.Unwrap(...); err != nil {
if strings.Contains(err.Error(), "malformed file-key stanza") {
// treat plugin as incompatible: report version, suggest upgrade
}
} Prevention
- Keep plugin binaries updated to spec-conforming versions
- Test plugins with the age-plugin-test-tool suite
- Pin plugin versions; avoid shadowing scripts on PATH
When it happens
Trigger: A plugin binary writes a 'file-key' stanza with zero or two or more space-separated arguments (e.g. writeStanza(conn, "file-key", args...) called with wrong arity) while the client's Unwrap/UnwrapWithLabels is reading its response.
Common situations: Custom or third-party age plugins that hand-roll the plugin protocol and emit a malformed file-key stanza; plugin versions that predate or diverge from the v1 protocol; a plugin binary on PATH that is actually a different/older program responding with an unexpected format.
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 file-key stanza: invalid index
- malformed file-key stanza: unexpected index
- received duplicated file-key stanza
- malformed confirm stanza: unexpected number of arguments
- malformed confirm stanza: invalid YES option encoding
AI-assisted analysis of FiloSottile/age@b74dce4cdb (2026-08-31).
Data as JSON: /api/errors/4ed2604935a9960c.
Report an issue: GitHub.