FiloSottile/age · error
invalid plugin name: %q
Error message
invalid plugin name: %q
What it means
NewIdentityWithoutData validates the plugin name by checking that EncodeIdentity(name, nil) produces a non-empty identity encoding. If it returns empty, the name is not a recognized/supported plugin identity name and construction fails, preventing Identity objects for plugins that cannot encode identities.
Source
Thrown at plugin/client.go:193
ui *ClientUI
}
var _ age.Identity = &Identity{}
func NewIdentity(s string, ui *ClientUI) (*Identity, error) {
name, _, err := ParseIdentity(s)
if err != nil {
return nil, err
}
return &Identity{
name: name, encoding: s, ui: ui,
}, nil
}
func NewIdentityWithoutData(name string, ui *ClientUI) (*Identity, error) {
s := EncodeIdentity(name, nil)
if s == "" {
return nil, fmt.Errorf("invalid plugin name: %q", name)
}
return &Identity{
name: strings.ToLower(name), encoding: s, ui: ui,
}, nil
}
// Name returns the plugin name, which is used in the recipient ("age1name1...")
// and identity ("AGE-PLUGIN-NAME-1...") encodings, as well as in the plugin
// binary name ("age-plugin-name").
func (i *Identity) Name() string {
return i.name
}
// String returns the identity encoding string ("AGE-PLUGIN-NAME-1...").
func (i *Identity) String() string {
return i.encoding
}
View on GitHub (pinned to b74dce4cdb)
Solutions
- Pass the exact supported plugin name and check for typos or stray whitespace.
- Confirm the plugin supports identities; recipient-only plugins cannot be used with NewIdentityWithoutData.
- Reject empty/blank names at config load time before calling.
- If the plugin is legitimate but unsupported, upgrade the age library/plugin to a version that knows its identity encoding.
Example fix
// before
name := os.Getenv("AGE_PLUGIN") // may be ""
identity, err := age.NewIdentityWithoutData(name, ui) // invalid plugin name: ""
// after
name := strings.TrimSpace(os.Getenv("AGE_PLUGIN"))
if name == "" {
return fmt.Errorf("AGE_PLUGIN must be set to a supported plugin name")
}
identity, err := age.NewIdentityWithoutData(name, ui) Defensive patterns
Strategy: validation
Validate before calling
// Go: validate the plugin name before constructing the identity
name := strings.TrimSpace(cfg.PluginName)
if name == "" {
return fmt.Errorf("plugin name must not be empty")
} Type guard
func validPluginName(name string) bool {
return name != "" && strings.TrimSpace(name) == name &&
plugin.EncodeIdentity(name, nil) != "" // maps to a known identity encoding
} Try / catch
identity, err := plugin.NewIdentityWithoutData(name, ui)
if err != nil {
return fmt.Errorf("unsupported plugin identity %q: %w", name, err)
} Prevention
- Trim and validate plugin names at config load time.
- Only use plugin names whose plugins support identity encoding (not recipient-only).
- Keep the plugin and age library versions aligned so all prefixes are known.
- Reject empty/whitespace names early with a clear configuration error.
When it happens
Trigger: Calling NewIdentityWithoutData with a name whose prefix has no registered identity encoding: an empty string, a misspelled plugin name, or a plugin that only supports recipients (no identity scheme). Called by encryptNotPass/decryptNotPass and tests.
Common situations: Typo in the plugin name in config or code; using a recipient-only plugin with the identity constructor; a library version that does not know the plugin's identity encoding; empty name from an unset environment variable or config key.
Related errors
- %s plugin: %w
- couldn't start plugin: %w
- malformed recipient stanza: unexpected argument count
- malformed recipient stanza: invalid index
- malformed recipient stanza: unexpected index
AI-assisted analysis of FiloSottile/age@b74dce4cdb (2026-08-31).
Data as JSON: /api/errors/006f586d77517954.
Report an issue: GitHub.