{"record":{"id":"bd9aa8e377b8a948","repo":"FiloSottile/age","slug":"s","errorCode":null,"errorMessage":"%s","messagePattern":"%s","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/client.go","lineNumber":151,"sourceCode":"\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\")\n\t\t\t}\n\t\t\tlabels = s.Args\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 \"error\":\n\t\t\tif err := writeStanza(conn, \"ok\"); err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\n\t\t\treturn nil, nil, fmt.Errorf(\"%s\", s.Body)\n\t\tcase \"done\":\n\t\t\tbreak ReadLoop\n\t\tdefault:\n\t\t\tif ok, err := r.ui.handle(r.name, conn, s); err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t} else if !ok {\n\t\t\t\tif err := writeStanza(conn, \"unsupported\"); err != nil {\n\t\t\t\t\treturn nil, nil, err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif len(stanzas) == 0 {\n\t\treturn nil, nil, fmt.Errorf(\"received zero recipient stanzas\")\n\t}\n\n\treturn stanzas, labels, nil","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/FiloSottile/age/blob/b74dce4cdbe35b5e5f66c06d9612b72f89028758/plugin/client.go#L133-L169","documentation":"The plugin sent an 'error' stanza, indicating it failed on its side during the wrap protocol. The client surfaces the plugin's error body verbatim as the returned error, so this is the plugin's own failure message (device error, permission denial, unsupported recipient, etc.).","triggerScenarios":"Calling WrapWithLabels/Wrap when the plugin starts successfully but responds with an 'error' stanza, e.g. a YubiKey plugin cannot reach the key, the smartcard is locked, or the recipient is unsupported by the plugin.","commonSituations":"Hardware token not present or locked (PIN retries exhausted); touch/agent confirmation required but not granted; plugin does not recognize the recipient string; plugin-side internal errors.","solutions":["Read the error body text (it is the plugin's message) and act on it directly.","Verify the hardware/agent the plugin depends on is available and unlocked.","Validate the recipient string format for that plugin using its own tooling.","Update the plugin; if the message is an internal error, reproduce it with the plugin CLI and report upstream."],"exampleFix":"// before\nout, err := age.Wrap(...) // returns plugin body e.g. \"yubikey: device not found\"\n// after\nout, err := age.Wrap(...)\nif err != nil {\n    if strings.Contains(err.Error(), \"device not found\") {\n        return fmt.Errorf(\"plug in the YubiKey and retry: %w\", err)\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"// Go: pre-check the device/agent the plugin depends on when possible\n// e.g. run the plugin's own list/status command to verify the key is reachable","typeGuard":null,"tryCatchPattern":"stanzas, labels, err := client.WrapWithLabels(fileKey)\nif err != nil {\n    body := strings.TrimSpace(err.Error()) // plugin's own error text\n    if strings.Contains(body, \"device not found\") || strings.Contains(body, \"PIN\") {\n        return fmt.Errorf(\"unlock/present the hardware token: %s\", body)\n    }\n    return fmt.Errorf(\"plugin reported: %s\", body)\n}","preventionTips":["Surface plugin error bodies verbatim to users; they describe the plugin-side cause.","Ensure hardware tokens/agents are available and unlocked before encrypting.","Validate recipient formats with the plugin's own CLI before programmatic use.","Keep plugins updated; internal plugin errors are often fixed upstream."],"tags":["go","age","plugin","protocol","remote-error"],"backgroundTag":"plugin-reported-failure","analyzedSha":"b74dce4cdbe35b5e5f66c06d9612b72f89028758","analyzedAt":"2026-08-31T23:59:31.627Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}