{"record":{"id":"a75fb8621d6d4e44","repo":"FiloSottile/age","slug":"malformed-recipient-stanza-invalid-index","errorCode":null,"errorMessage":"malformed recipient stanza: invalid index","messagePattern":"malformed recipient stanza: invalid index","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/client.go","lineNumber":121,"sourceCode":"\t}\n\n\t// Phase 2: plugin responds with stanzas\n\tsr := format.NewStanzaReader(bufio.NewReader(conn))\nReadLoop:\n\tfor {\n\t\ts, err := r.ui.readStanza(r.name, sr)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\n\t\tswitch s.Type {\n\t\tcase \"recipient-stanza\":\n\t\t\tif len(s.Args) < 2 {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"malformed recipient stanza: unexpected argument 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, nil, fmt.Errorf(\"malformed recipient 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, nil, fmt.Errorf(\"malformed recipient stanza: unexpected index\")\n\t\t\t}\n\n\t\t\tstanzas = append(stanzas, &age.Stanza{\n\t\t\t\tType: s.Args[1],\n\t\t\t\tArgs: s.Args[2:],\n\t\t\t\tBody: s.Body,\n\t\t\t})\n\n\t\t\tif err := writeStanza(conn, \"ok\"); err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\tcase \"labels\":\n\t\t\tif labels != nil {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"repeated labels stanza\")","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/FiloSottile/age/blob/b74dce4cdbe35b5e5f66c06d9612b72f89028758/plugin/client.go#L103-L139","documentation":"The plugin sent a recipient-stanza whose first argument (the file-key index) is not a valid decimal integer, so strconv.Atoi failed. The protocol requires Args[0] to be the numeric index of the wrapped file key; anything else is rejected as malformed.","triggerScenarios":"WrapWithLabels/Wrap receives a recipient-stanza where Args[0] is a non-numeric string, e.g. the plugin omitted the index or put the stanza type first.","commonSituations":"Old or non-conformant plugin versions that send stanzas without the leading index; a plugin written against a different protocol revision; argument ordering bugs in a plugin under development.","solutions":["Upgrade the plugin to a version matching the current recipient-v1 protocol (numeric index as first arg).","Fix the plugin's stanza writer so Args[0] is the decimal file-key index ('0' for a single file key).","Capture the raw stanza to verify the argument layout before filing a bug with the plugin author.","Pin known-good plugin versions to avoid mixing protocol revisions."],"exampleFix":"// before (plugin side)\nwriteStanza(conn, \"recipient-stanza\", \"x25519\", body) // no index, type first\n// after\nwriteStanza(conn, \"recipient-stanza\", \"0\", \"x25519\", body)","handlingStrategy":"validation","validationCode":"// Go: ensure the index argument parses before use\nif _, err := strconv.Atoi(args[0]); err != nil {\n    return fmt.Errorf(\"plugin sent non-numeric stanza index %q\", args[0])\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"invalid index\") {\n        return fmt.Errorf(\"plugin protocol mismatch (missing numeric index); upgrade plugin: %w\", err)\n    }\n    return err\n}","preventionTips":["Write plugin stanzas with the numeric index as the first argument.","Run integration tests between your plugin and the age client after every protocol change.","Version-check the plugin binary at startup if possible.","Report non-conformant plugins upstream rather than working around them."],"tags":["go","age","plugin","protocol","malformed-data"],"backgroundTag":"plugin-protocol-violation","analyzedSha":"b74dce4cdbe35b5e5f66c06d9612b72f89028758","analyzedAt":"2026-08-31T23:59:31.627Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}