{"record":{"id":"5c5b9268862e62c0","repo":"FiloSottile/age","slug":"failed-to-read-unsupported-stanza-v","errorCode":null,"errorMessage":"failed to read unsupported stanza: %v","messagePattern":"failed to read unsupported stanza: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/plugin.go","lineNumber":661,"sourceCode":"\t\treturn nil, fmt.Errorf(\"failed to read response stanza: %v\", err)\n\t}\n\tswitch s.Type {\n\tcase \"fail\":\n\t\tif err := expectStanzaWithNoBody(s, 0); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%v\", err)\n\t\t}\n\t\treturn s, nil\n\tcase \"ok\":\n\t\treturn s, nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"expected ok or fail stanza, got %q\", s.Type)\n\t}\n}\n\nfunc expectUnsupported(sr *format.StanzaReader) error {\n\tunsupported, err := sr.ReadStanza()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read unsupported stanza: %v\", err)\n\t}\n\tif unsupported.Type != \"unsupported\" {\n\t\treturn fmt.Errorf(\"expected unsupported stanza, got %q\", unsupported.Type)\n\t}\n\treturn expectStanzaWithNoBody(unsupported, 0)\n}\n\nfunc (p *Plugin) writeError(args []string, err error) error {\n\ts := &format.Stanza{Type: \"error\", Args: args}\n\ts.Body = []byte(err.Error())\n\tif err := s.Marshal(p.stdout); err != nil {\n\t\treturn fmt.Errorf(\"failed to write error stanza: %v\", err)\n\t}\n\tif err := expectOk(p.sr); err != nil {\n\t\treturn fmt.Errorf(\"%v\", err)\n\t}\n\treturn nil\n}","sourceCodeStart":643,"sourceCodeEnd":679,"githubUrl":"https://github.com/FiloSottile/age/blob/b74dce4cdbe35b5e5f66c06d9612b72f89028758/plugin/plugin.go#L643-L679","documentation":"expectUnsupported is used when the client probes whether the plugin supports a command (unsupported-stanza handshake in RecipientV1/IdentityV1). A ReadStanza failure here — EOF, broken pipe, or bad framing — is wrapped with this message. It means the plugin never delivered the 'unsupported' acknowledgment the probe expected.","triggerScenarios":"During RecipientV1/IdentityV1 negotiation the client reads for an 'unsupported' reply; the plugin exits, crashes, or emits a stanza with invalid framing so ReadStanza errors before any 'unsupported' arrives.","commonSituations":"Plugin binary missing or failing to exec (though that usually fails earlier, at pipe setup); plugin panics on the probing command; plugin speaks a protocol without the unsupported handshake and just terminates; environment issues like a non-executable or wrong-architecture plugin binary.","solutions":["Verify the plugin binary runs standalone and does not crash on the probe command","Check the plugin's stderr output for a panic or early exit","Confirm the plugin implements the command-unsupported reply of the plugin protocol","Reinstall/upgrade the plugin and check the AGE_PLUGIN path points to the right binary"],"exampleFix":"// before (plugin side) — exits without replying to unknown command\nif cmd != \"recipient-v1\" { os.Exit(1) }\n\n// after\nif cmd != \"recipient-v1\" { fmt.Printf(\"-> unsupported\\n\\n\"); return }","handlingStrategy":"try-catch","validationCode":"if _, err := os.Stat(pluginPath); err != nil {\n    return fmt.Errorf(\"plugin binary %q not found: %w\", pluginPath, err)\n}\nif err := exec.Command(pluginPath).Run(); err != nil {\n    return fmt.Errorf(\"plugin binary not executable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := expectUnsupported(sr); err != nil {\n    if strings.Contains(err.Error(), \"failed to read unsupported stanza\") {\n        return fmt.Errorf(\"plugin %s crashed during capability probe: %w (stderr: %s)\", pluginName, err, stderrBuf.String())\n    }\n    return err\n}","preventionTips":["Verify plugin binary exists, is executable, and runs before use","Ensure the plugin answers unknown commands with 'unsupported' instead of exiting","Probe plugin capabilities once at startup and cache the result"],"tags":["age","plugin-protocol","io","unsupported-command"],"backgroundTag":"plugin-protocol-io-failure","analyzedSha":"b74dce4cdbe35b5e5f66c06d9612b72f89028758","analyzedAt":"2026-08-31T23:59:31.627Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}