{"record":{"id":"b967ec032d8ed656","repo":"FiloSottile/age","slug":"failed-to-read-response-stanza-v","errorCode":null,"errorMessage":"failed to read response stanza: %v","messagePattern":"failed to read response stanza: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/plugin.go","lineNumber":643,"sourceCode":"\t}\n\treturn 3\n}\n\nfunc expectOk(sr *format.StanzaReader) error {\n\tok, err := sr.ReadStanza()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read OK stanza: %v\", err)\n\t}\n\tif ok.Type != \"ok\" {\n\t\treturn fmt.Errorf(\"expected OK stanza, got %q\", ok.Type)\n\t}\n\treturn expectStanzaWithNoBody(ok, 0)\n}\n\nfunc readOkOrFail(sr *format.StanzaReader) (*format.Stanza, error) {\n\ts, err := sr.ReadStanza()\n\tif err != nil {\n\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)","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/FiloSottile/age/blob/b74dce4cdbe35b5e5f66c06d9612b72f89028758/plugin/plugin.go#L625-L661","documentation":"readOkOrFail reads the next stanza for interactive commands (DisplayMessage, RequestValue, Confirm) and wraps any ReadStanza failure with this message. The client needs either 'ok' or 'fail' to continue but the stream broke first — typically the plugin died mid-dialog or emitted unparseable framing.","triggerScenarios":"During a Confirm or RequestValue exchange the plugin's stdout yields an I/O error or unexpected EOF instead of a well-formed stanza; missing blank-line terminator on the plugin's reply.","commonSituations":"Plugin crashes while prompting the user; user aborts and the plugin kills its own output pipe; long-running prompt exceeds a timeout and the pipe is reaped; plugin writes a stanza without its empty-line terminator.","solutions":["Inspect the plugin's stderr for a crash or abort message at the time of the dialog","Re-run the operation to see if the failure is reproducible or a transient pipe issue","Verify the plugin writes complete stanzas (data lines plus terminating blank line)","Update the plugin to the latest version and retest"],"exampleFix":"// before (plugin side)\nfmt.Printf(\"-> ok\") // no terminating blank line\n\n// after\nfmt.Printf(\"-> ok\\n\\n\")","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"s, err := readOkOrFail(sr)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to read response stanza\") {\n        return fmt.Errorf(\"plugin %s ended mid-dialog: %w\", pluginName, err)\n    }\n    return err\n}","preventionTips":["Guard against the user/OS killing the plugin during prompts","Ensure prompts complete before the plugin exits","Log plugin stderr for crash diagnosis"],"tags":["age","plugin-protocol","io","interactive-prompt"],"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"}