{"record":{"id":"25bc1c7cded4eb83","repo":"derailed/k9s","slug":"duplicate-input-name-q","errorCode":null,"errorMessage":"duplicate input name %q","messagePattern":"duplicate input name %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/plugin.go","lineNumber":87,"sourceCode":"func (p Plugin) String() string {\n\treturn fmt.Sprintf(\"[%s] %s(%s)\", p.ShortCut, p.Command, strings.Join(p.Args, \" \"))\n}\n\n// ShouldConfirm returns whether the plugin should show a confirmation dialog.\n// Defaults to true when inputs are defined, false otherwise.\nfunc (p *Plugin) ShouldConfirm() bool {\n\tif p.Confirm != nil {\n\t\treturn *p.Confirm\n\t}\n\treturn len(p.Inputs) > 0\n}\n\n// Validate checks the plugin configuration for errors.\nfunc (p *Plugin) Validate() error {\n\tseen := make(map[string]struct{}, len(p.Inputs))\n\tfor _, input := range p.Inputs {\n\t\tif _, ok := seen[input.Name]; ok {\n\t\t\treturn fmt.Errorf(\"duplicate input name %q\", input.Name)\n\t\t}\n\t\tseen[input.Name] = struct{}{}\n\n\t\tif input.Default == \"\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tswitch input.Type {\n\t\tcase InputTypeDropdown:\n\t\t\tif !slices.Contains(input.Options, input.Default) {\n\t\t\t\treturn fmt.Errorf(\"default value %q for input %q is not a valid option\", input.Default, input.Name)\n\t\t\t}\n\t\tcase InputTypeBool:\n\t\t\tif input.Default != \"true\" && input.Default != \"false\" {\n\t\t\t\treturn fmt.Errorf(\"default value %q for bool input %q must be \\\"true\\\" or \\\"false\\\"\", input.Default, input.Name)\n\t\t\t}\n\t\tcase InputTypeNumber:\n\t\t\tif _, err := strconv.ParseFloat(input.Default, 64); err != nil {","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/config/plugin.go#L69-L105","documentation":"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.","triggerScenarios":"Defining a plugin with inputs: [{name: ns, ...}, {name: ns, ...}] — typically copy-paste of an input block where the second name was not updated.","commonSituations":"Building multi-prompt plugins (namespace + resource name) by duplicating YAML blocks; merging plugin definitions from examples; refactoring inputs and leaving a stale duplicate behind.","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"],"exampleFix":"# before\nplugins:\n  myplug:\n    ... \n    inputs:\n      - name: ns\n        type: string\n      - name: ns        # duplicate\n        type: string\n\n# after\n      - name: ns\n        type: string\n      - name: resource\n        type: string","handlingStrategy":"validation","validationCode":"func inputNamesUnique(p Plugin) bool {\n\tseen := make(map[string]struct{}, len(p.Inputs))\n\tfor _, in := range p.Inputs {\n\t\tif _, dup := seen[in.Name]; dup {\n\t\t\treturn false\n\t\t}\n\t\tseen[in.Name] = struct{}{}\n\t}\n\treturn true\n}","typeGuard":null,"tryCatchPattern":"if err := plugin.Validate(); err != nil {\n\tif strings.Contains(err.Error(), \"duplicate input name\") {\n\t\t// skip this plugin file, keep loading others; surface the name in UI\n\t}\n}","preventionTips":["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"],"tags":["k9s","plugins","validation","config","yaml"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}