derailed/k9s · error
duplicate input name %q
Error message
duplicate input name %q
What it means
Returned by Plugin.Validate (internal/config/plugin.go:87) when two entries in a plugin's inputs list share the same name. Input names key the prompt form and the value substitution map, so duplicates are ambiguous and rejected. Via Plugins.load this surfaces as 'plugin validation failed for <file>: duplicate input name ...' and the whole plugin file is skipped — the plugin simply does not register.
Source
Thrown at internal/config/plugin.go:87
func (p Plugin) String() string {
return fmt.Sprintf("[%s] %s(%s)", p.ShortCut, p.Command, strings.Join(p.Args, " "))
}
// ShouldConfirm returns whether the plugin should show a confirmation dialog.
// Defaults to true when inputs are defined, false otherwise.
func (p *Plugin) ShouldConfirm() bool {
if p.Confirm != nil {
return *p.Confirm
}
return len(p.Inputs) > 0
}
// Validate checks the plugin configuration for errors.
func (p *Plugin) Validate() error {
seen := make(map[string]struct{}, len(p.Inputs))
for _, input := range p.Inputs {
if _, ok := seen[input.Name]; ok {
return fmt.Errorf("duplicate input name %q", input.Name)
}
seen[input.Name] = struct{}{}
if input.Default == "" {
continue
}
switch input.Type {
case InputTypeDropdown:
if !slices.Contains(input.Options, input.Default) {
return fmt.Errorf("default value %q for input %q is not a valid option", input.Default, input.Name)
}
case InputTypeBool:
if input.Default != "true" && input.Default != "false" {
return fmt.Errorf("default value %q for bool input %q must be \"true\" or \"false\"", input.Default, input.Name)
}
case InputTypeNumber:
if _, err := strconv.ParseFloat(input.Default, 64); err != nil {View on GitHub (pinned to 2d3ccc6ba2)
Solutions
- Open the plugin file named in the error and make each input's name unique (e.g. namespace, resource_name)
- If the duplicate was intentional duplication of behavior, merge the two inputs into one
- Re-run k9s and confirm the plugin appears in :plugins
Example fix
# before
plugins:
myplug:
...
inputs:
- name: ns
type: string
- name: ns # duplicate
type: string
# after
- name: ns
type: string
- name: resource
type: string Defensive patterns
Strategy: validation
Validate before calling
func inputNamesUnique(p Plugin) bool {
seen := make(map[string]struct{}, len(p.Inputs))
for _, in := range p.Inputs {
if _, dup := seen[in.Name]; dup {
return false
}
seen[in.Name] = struct{}{}
}
return true
} Try / catch
if err := plugin.Validate(); err != nil {
if strings.Contains(err.Error(), "duplicate input name") {
// skip this plugin file, keep loading others; surface the name in UI
}
} Prevention
- Run plugin.Validate() in a lint step over plugin files instead of discovering failures at launch
- When copy-pasting an input block, change the name first — duplicates are the #1 cause
- Keep inputs list short and review names before saving the file
When it happens
Trigger: Defining a plugin with inputs: [{name: ns, ...}, {name: ns, ...}] — typically copy-paste of an input block where the second name was not updated.
Common situations: Building multi-prompt plugins (namespace + resource name) by duplicating YAML blocks; merging plugin definitions from examples; refactoring inputs and leaving a stale duplicate behind.
Related errors
- default value %q for bool input %q must be "true" or "false"
- k9s config file %q load failed: %w
- default value %q for input %q is not a valid option
- default value %q for number input %q is not a valid number
- plugin validation failed for %s: %w
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/25bc1c7cded4eb83.
Report an issue: GitHub.