{"record":{"id":"ec7ba0c59e5bb4b3","repo":"FiloSottile/age","slug":"s-plugin-w","errorCode":null,"errorMessage":"%s plugin: %w","messagePattern":"(.+?) plugin: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/client.go","lineNumber":74,"sourceCode":"\n// String returns the recipient encoding string (\"age1name1...\") or\n// \"<identity-based recipient>\" if r was created by [Identity.Recipient].\nfunc (r *Recipient) String() string {\n\tif r.identity {\n\t\treturn \"<identity-based recipient>\"\n\t}\n\treturn r.encoding\n}\n\nfunc (r *Recipient) Wrap(fileKey []byte) (stanzas []*age.Stanza, err error) {\n\tstanzas, _, err = r.WrapWithLabels(fileKey)\n\treturn\n}\n\nfunc (r *Recipient) WrapWithLabels(fileKey []byte) (stanzas []*age.Stanza, labels []string, err error) {\n\tdefer func() {\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"%s plugin: %w\", r.name, err)\n\t\t}\n\t}()\n\n\tconn, err := openClientConnection(r.name, \"recipient-v1\")\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"couldn't start plugin: %w\", err)\n\t}\n\tdefer conn.Close()\n\n\t// Phase 1: client sends recipient or identity and file key\n\taddType := \"add-recipient\"\n\tif r.identity {\n\t\taddType = \"add-identity\"\n\t}\n\tif err := writeStanza(conn, addType, r.encoding); err != nil {\n\t\treturn nil, nil, err\n\t}\n\tif _, err := writeGrease(conn); err != nil {","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/FiloSottile/age/blob/b74dce4cdbe35b5e5f66c06d9612b72f89028758/plugin/client.go#L56-L92","documentation":"This is the plugin error wrapper in plugin.Recipient.WrapWithLabels: when any step of the age-plugin protocol fails, the returned error is prefixed with \"<plugin-name> plugin: \" so users can tell which plugin failed. It is not itself a failure condition; it decorates the underlying cause (couldn't start plugin, protocol error, plugin-reported failure) from the recipient-v1 wrap interaction.","triggerScenarios":"Calling Wrap or WrapWithLabels on a plugin Recipient when: the plugin binary age-plugin-<name> is not found or fails to start; the plugin exits early or speaks a malformed protocol; the plugin reports an error stanza during wrap; any connection or stanza write fails.","commonSituations":"Plugin not installed or not on PATH; wrong plugin binary version (mismatched plugin protocol); a plugin that crashes on the given recipient encoding; corrupted or unsupported recipient string; container/CI environments missing the plugin binary.","solutions":["Check the wrapped error after the prefix: 'couldn't start plugin' means install/fix the age-plugin-<name> binary on PATH.","Verify the plugin binary is executable and its version matches the age library/plugin protocol you use.","Validate the recipient string; re-export it from the source plugin if the encoding is corrupt.","Run the plugin binary directly with the same recipient to see its native error output and debug its configuration.","Update both age and the plugin to compatible versions if the protocol handshake fails."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Verify the plugin is available before wrapping\nname := recipient.Name()\nif _, err := exec.LookPath(\"age-plugin-\" + name); err != nil {\n    return fmt.Errorf(\"plugin binary age-plugin-%s not found on PATH\", name)\n}","typeGuard":null,"tryCatchPattern":"stanzas, err := recipient.Wrap(fileKey)\nif err != nil {\n    // err looks like: \"<name> plugin: <cause>\"\n    msg := err.Error()\n    if i := strings.Index(msg, \" plugin: \"); i >= 0 {\n        cause := msg[i+len(\" plugin: \"):]\n        log.Printf(\"plugin failure cause: %s\", cause)\n    }\n    return err\n}","preventionTips":["Install the matching age-plugin-<name> binary and keep it on PATH.","Pin compatible versions of age and each plugin.","Test recipient encodings by running the plugin standalone before production use.","Always read the text after the '<name> plugin:' prefix; it names the real failure."],"tags":["plugin","error-wrapping","age","go"],"backgroundTag":"plugin-not-found","analyzedSha":"b74dce4cdbe35b5e5f66c06d9612b72f89028758","analyzedAt":"2026-08-31T23:59:31.627Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}