{"record":{"id":"227eda7c524f36c4","repo":"FiloSottile/age","slug":"malformed-file-key-stanza-unexpected-index","errorCode":null,"errorMessage":"malformed file-key stanza: unexpected index","messagePattern":"malformed file-key stanza: unexpected index","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/client.go","lineNumber":278,"sourceCode":"ReadLoop:\n\tfor {\n\t\ts, err := i.ui.readStanza(i.name, sr)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tswitch s.Type {\n\t\tcase \"file-key\":\n\t\t\tif len(s.Args) != 1 {\n\t\t\t\treturn nil, fmt.Errorf(\"malformed file-key stanza: unexpected arguments count\")\n\t\t\t}\n\t\t\tn, err := strconv.Atoi(s.Args[0])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"malformed file-key stanza: invalid index\")\n\t\t\t}\n\t\t\t// We only send a single file key, so the index must be 0.\n\t\t\tif n != 0 {\n\t\t\t\treturn nil, fmt.Errorf(\"malformed file-key stanza: unexpected index\")\n\t\t\t}\n\t\t\tif fileKey != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"received duplicated file-key stanza\")\n\t\t\t}\n\n\t\t\tfileKey = s.Body\n\n\t\t\tif err := writeStanza(conn, \"ok\"); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\tcase \"error\":\n\t\t\tif err := writeStanza(conn, \"ok\"); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\treturn nil, fmt.Errorf(\"%s\", s.Body)\n\t\tcase \"done\":\n\t\t\tbreak ReadLoop","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/FiloSottile/age/blob/b74dce4cdbe35b5e5f66c06d9612b72f89028758/plugin/client.go#L260-L296","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (plugin side)\nwriteStanza(w, \"file-key\", strconv.Itoa(fileIdx))\n// after\nwriteStanza(w, \"file-key\", \"0\")","handlingStrategy":"validation","validationCode":"// Ensure your tooling submits exactly one file per plugin invocation\nif len(files) != 1 { return errors.New(\"plugin protocol supports one file per invocation\") }","typeGuard":null,"tryCatchPattern":"if err := unwrap(); err != nil {\n    if strings.Contains(err.Error(), \"unexpected index\") {\n        return fmt.Errorf(\"plugin is multi-file/misindexed; upgrade or replace plugin\")\n    }\n}","preventionTips":["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"],"tags":["go","age","plugin-protocol","stanza-parsing"],"backgroundTag":"plugin-protocol-violation","analyzedSha":"b74dce4cdbe35b5e5f66c06d9612b72f89028758","analyzedAt":"2026-08-31T23:59:31.627Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}