FiloSottile/age · error

invalid plugin name

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.

Solutions

  1. Pass the exact supported plugin name and check for typos or stray whitespace.
  2. Confirm the plugin supports identities; recipient-only plugins cannot be used with NewIdentityWithoutData.
  3. Reject empty/blank names at config load time before calling.
  4. 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

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


AI-assisted analysis of FiloSottile/age@b74dce4cdb (2026-08-31). Data as JSON: /api/errors/006f586d77517954. Report an issue: GitHub.

Appendix: 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)