FiloSottile/age · error
malformed file-key stanza: unexpected index
Error message
malformed file-key stanza: unexpected index
What it means
The file-key stanza's index parsed fine but was not 0. The age Go library always sends exactly one file to a plugin per invocation, so the only valid index is 0; any other index means the plugin is not following the v1 protocol.
Source
Thrown at plugin/client.go:278
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
}
case "error":
if err := writeStanza(conn, "ok"); err != nil {
return nil, err
}
return nil, fmt.Errorf("%s", s.Body)
case "done":
break ReadLoopView on GitHub (pinned to b74dce4cdb)
Solutions
- Fix or update the plugin to always send index 0 (writeStanza(w, "file-key", "0"))
- Ensure only one file is submitted per plugin invocation — split multi-file work across invocations
- Confirm the plugin's protocol label (age-plugin v1) and behavior match what this library expects
Example fix
// before (plugin side) writeStanza(w, "file-key", strconv.Itoa(fileIdx)) // after writeStanza(w, "file-key", "0")
Defensive patterns
Strategy: validation
Validate before calling
// Ensure your tooling submits exactly one file per plugin invocation
if len(files) != 1 { return errors.New("plugin protocol supports one file per invocation") } Try / catch
if err := unwrap(); err != nil {
if strings.Contains(err.Error(), "unexpected index") {
return fmt.Errorf("plugin is multi-file/misindexed; upgrade or replace plugin")
}
} Prevention
- Plugins must hardcode index 0 per the v1 spec
- Never reuse a batch-encryptor plugin for unwrap flows
- Validate plugins against the reference age client
When it happens
Trigger: A plugin echoes back a nonzero file index (e.g. "file-key 1") in response to a recipient-v1 or identity-v1 unwrap performed via Unwrap.
Common situations: Plugins reused from tooling that batch multiple files per session; plugin code that increments or misreads the index counter; hand-written plugins that assume multi-file semantics.
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: unexpected arguments count
- malformed file-key stanza: invalid 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/227eda7c524f36c4.
Report an issue: GitHub.