{"record":{"id":"e1ddd0f084ac1390","repo":"getsops/sops","slug":"failed-to-parse-input-as-age-key-from-age-plugin","errorCode":null,"errorMessage":"failed to parse input as age key from age plugin: %w","messagePattern":"failed to parse input as age key from age plugin: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"age/keysource.go","lineNumber":501,"sourceCode":"\t}\n\treturn identities, unusedLocations, errs\n}\n\n// parseRecipient attempts to parse a string containing an encoded age public\n// key or a public ssh key.\nfunc parseRecipient(recipient string) (age.Recipient, error) {\n\tswitch {\n\tcase strings.HasPrefix(recipient, \"age1pq1\"):\n\t\tparsedRecipient, err := age.ParseHybridRecipient(recipient)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse input as Bech32-encoded age public key: %w\", err)\n\t\t}\n\n\t\treturn parsedRecipient, nil\n\tcase strings.HasPrefix(recipient, \"age1\") && strings.Count(recipient, \"1\") > 1:\n\t\tparsedRecipient, err := plugin.NewRecipient(recipient, pluginTerminalUI)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse input as age key from age plugin: %w\", err)\n\t\t}\n\t\treturn parsedRecipient, nil\n\tcase strings.HasPrefix(recipient, \"age1\"):\n\t\tparsedRecipient, err := age.ParseX25519Recipient(recipient)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse input as Bech32-encoded age public key: %w\", err)\n\t\t}\n\n\t\treturn parsedRecipient, nil\n\tcase strings.HasPrefix(recipient, \"ssh-\"):\n\t\tparsedRecipient, err := agessh.ParseRecipient(recipient)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse input as age-ssh public key: %w\", err)\n\t\t}\n\t\treturn parsedRecipient, nil\n\t}\n\n\treturn nil, fmt.Errorf(\"failed to parse input, unknown recipient type: %q\", recipient)","sourceCodeStart":483,"sourceCodeEnd":519,"githubUrl":"https://github.com/getsops/sops/blob/13442bb98183887d7a9ac09ec8ab0564673a59d8/age/keysource.go#L483-L519","documentation":"The recipient matched the age plugin format (age1... with multiple '1' separators, i.e. a plugin recipient like age1yubikey1...) and sops invoked the corresponding age plugin binary via plugin.NewRecipient, but the plugin failed — plugin binary missing, plugin erroring, or an invalid recipient string for that plugin. The chained error carries the plugin's own failure message.","triggerScenarios":"parseRecipient routes a multi-'1' age1 recipient to plugin.NewRecipient; the plugin executable is absent from PATH, exits with an error, cannot get a passphrase/PIN via the UI, or rejects the recipient.","commonSituations":"age-plugin-yubikey / age-plugin-sss not installed on a new machine; plugin requires a PIN interaction in a non-TTY CI job; recipient mistyped so the plugin can't resolve it; plugin version mismatch with the age library.","solutions":["Install the matching plugin binary and ensure it's on PATH (age-plugin-yubikey list, etc.).","Run the plugin standalone to verify it works: age -r <recipient> round-trip test.","In CI/non-TTY environments, provide the plugin's required secret via env (e.g. AGE_PLUGIN_YUBIKEY_PIN or the plugin's documented variable) since interactive prompts fail.","Verify the recipient string matches what the plugin generated (plugin name/arguments embedded in the recipient).","Upgrade sops and the plugin to compatible versions."],"exampleFix":"// before (CI, no TTY, plugin needs PIN)\nsops -e -r age1yubikey1q... secrets.yaml\n// failed to parse input as age key from age plugin: plugin exited with error: PIN required\n\n// after\nexport AGE_PLUGIN_YUBIKEY_PIN=\"123456\"   # plugin's documented env var\nsops -e -r age1yubikey1q... secrets.yaml","handlingStrategy":"validation","validationCode":"// CI pre-flight: plugin must exist and recipient must be plugin-form\nRCPT=\"age1yubikey1...\"\ncase \"$RCPT\" in\n  age1* ) echo ok;;\n  * ) echo \"bad recipient\"; exit 1;;\nesac\ncommand -v age-plugin-yubikey >/dev/null || { echo \"plugin missing\"; exit 1; }","typeGuard":null,"tryCatchPattern":"rk, err := sopsage.MasterKeyFromRecipient(recipient)\nif err != nil && strings.Contains(err.Error(), \"age key from age plugin\") {\n    return fmt.Errorf(\"age plugin failed for %q: install/authorize plugin or provide PIN env: %w\", recipient, err)\n}","preventionTips":["Install and smoke-test the plugin (plugin's own list/show command) on every host in the runbook.","Export the plugin's non-interactive secret env vars in CI since TTY prompts fail.","Verify recipient strings against the plugin's documented format.","Pin plugin + sops versions together to avoid protocol drift.","Keep a recovery recipient (e.g. a second X25519 key) on files encrypted with plugin keys."],"tags":["age","plugin","recipient","exec"],"backgroundTag":"age-plugin-failed","analyzedSha":"13442bb98183887d7a9ac09ec8ab0564673a59d8","analyzedAt":"2026-09-01T03:53:00.447Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}