{"record":{"id":"48396603d47195d8","repo":"FiloSottile/age","slug":"not-a-plugin-identity-v","errorCode":null,"errorMessage":"not a plugin identity: %v","messagePattern":"not a plugin identity: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/encode.go","lineNumber":35,"sourceCode":"// EncodeIdentity encodes a plugin identity string for a plugin with the given\n// name. If the name is invalid, it returns an empty string.\nfunc EncodeIdentity(name string, data []byte) string {\n\tif !validPluginName(name) {\n\t\treturn \"\"\n\t}\n\ts, _ := bech32.Encode(\"AGE-PLUGIN-\"+strings.ToUpper(name)+\"-\", data)\n\treturn s\n}\n\n// ParseIdentity decodes a plugin identity string. It returns the plugin name\n// in lowercase and the encoded data.\nfunc ParseIdentity(s string) (name string, data []byte, err error) {\n\thrp, data, err := bech32.Decode(s)\n\tif err != nil {\n\t\treturn \"\", nil, fmt.Errorf(\"invalid identity encoding: %v\", err)\n\t}\n\tif !strings.HasPrefix(hrp, \"AGE-PLUGIN-\") || !strings.HasSuffix(hrp, \"-\") {\n\t\treturn \"\", nil, fmt.Errorf(\"not a plugin identity: %v\", err)\n\t}\n\tname = strings.TrimSuffix(strings.TrimPrefix(hrp, \"AGE-PLUGIN-\"), \"-\")\n\tname = strings.ToLower(name)\n\tif !validPluginName(name) {\n\t\treturn \"\", nil, fmt.Errorf(\"invalid plugin name: %q\", name)\n\t}\n\treturn name, data, nil\n}\n\n// EncodeRecipient encodes a plugin recipient string for a plugin with the given\n// name. If the name is invalid, it returns an empty string.\nfunc EncodeRecipient(name string, data []byte) string {\n\tif !validPluginName(name) {\n\t\treturn \"\"\n\t}\n\ts, _ := bech32.Encode(\"age1\"+strings.ToLower(name), data)\n\treturn s\n}","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/FiloSottile/age/blob/b74dce4cdbe35b5e5f66c06d9612b72f89028758/plugin/encode.go#L17-L53","documentation":"ParseIdentity decodes a bech32 string and requires the human-readable part to start with 'AGE-PLUGIN-' and end with '-'. If the prefix/suffix check fails, the library rejects the string as not being a plugin identity encoding. This guards against passing native age identities (e.g. AGE-SECRET-KEY-...) or arbitrary strings to the plugin API.","triggerScenarios":"Calling plugin.ParseIdentity (directly or via plugin.NewIdentity) with a bech32 string whose hrp is not AGE-PLUGIN-<name>- — e.g. a native 'AGE-SECRET-KEY-1...' identity, an 'age1...' recipient, or a plugin string missing the trailing dash.","commonSituations":"Developers confuse native age identity files with plugin identity strings; pass a recipient string where an identity is expected; hand-truncate or reformat a plugin identity losing the trailing '-'; paste strings from docs with wrong case for the hrp (bech32 hrp is lowercase, but the plugin convention uses AGE-PLUGIN-).","solutions":["Verify the string is a plugin identity: it must be bech32 and its hrp must match AGE-PLUGIN-<name>- exactly.","If it is a native age identity (AGE-SECRET-KEY-...), parse it with the age/crypto package instead of the plugin package.","Restore the trailing '-' if the string was truncated.","Call ParseIdentity only on identity strings produced by EncodeIdentity or the plugin itself."],"exampleFix":"// before\nname, data, err := plugin.ParseIdentity(\"AGE-SECRET-KEY-1QQQQ...\")\n// after\nif strings.HasPrefix(idStr, \"AGE-SECRET-KEY-\") { /* use native age identity parser */ }\nname, data, err := plugin.ParseIdentity(\"AGE-PLUGIN-FROOD-1QQQQ...\")","handlingStrategy":"validation","validationCode":"func looksLikePluginIdentity(s string) bool {\n\thrp, _, err := bech32.Decode(s)\n\treturn err == nil && strings.HasPrefix(hrp, \"AGE-PLUGIN-\") && strings.HasSuffix(hrp, \"-\")\n}","typeGuard":"func isPluginIdentity(s string) bool { return looksLikePluginIdentity(s) }","tryCatchPattern":"name, data, err := plugin.ParseIdentity(s)\nif err != nil {\n\tif strings.Contains(err.Error(), \"not a plugin identity\") { return fmt.Errorf(\"%q is not a plugin identity (expected AGE-PLUGIN-...)\", s) }\n\treturn err\n}","preventionTips":["Check for the AGE-PLUGIN- prefix and trailing '-' before parsing","Use the native age identity parser for AGE-SECRET-KEY strings","Never hand-edit plugin identity strings","Store identities verbatim from EncodeIdentity output"],"tags":["go","bech32","parsing","age-encryption"],"backgroundTag":"invalid-encoding-format","analyzedSha":"b74dce4cdbe35b5e5f66c06d9612b72f89028758","analyzedAt":"2026-08-31T23:59:31.627Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}