{"record":{"id":"b63296731b735248","repo":"caddyserver/caddy","slug":"command-already-registered-s","errorCode":null,"errorMessage":"command already registered: %s","messagePattern":"command already registered: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cmd/commands.go","lineNumber":592,"sourceCode":"// if the name does not meet the described format, or if\n// any of the fields are missing from cmd.\n//\n// This function should be used in init().\nfunc RegisterCommand(cmd Command) {\n\tcommandsMu.Lock()\n\tdefer commandsMu.Unlock()\n\n\tif cmd.Name == \"\" {\n\t\tpanic(\"command name is required\")\n\t}\n\tif cmd.Func == nil && cmd.CobraFunc == nil {\n\t\tpanic(\"command function missing\")\n\t}\n\tif cmd.Short == \"\" {\n\t\tpanic(\"command short string is required\")\n\t}\n\tif _, exists := commands[cmd.Name]; exists {\n\t\tpanic(\"command already registered: \" + cmd.Name)\n\t}\n\tif !commandNameRegex.MatchString(cmd.Name) {\n\t\tpanic(\"invalid command name\")\n\t}\n\tdefaultFactory.Use(func(rootCmd *cobra.Command) {\n\t\trootCmd.AddCommand(caddyCmdToCobra(cmd))\n\t})\n\tcommands[cmd.Name] = cmd\n}\n\nvar commandNameRegex = regexp.MustCompile(`^[a-z0-9]$|^([a-z0-9]+-?[a-z0-9]*)+[a-z0-9]$`)\n","sourceCodeStart":574,"sourceCodeEnd":604,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/cmd/commands.go#L574-L604","documentation":"RegisterCommand panics when a command Name collides with one already registered. Command names are a flat, global namespace (commands map guarded by commandsMu), so two plugins — or a plugin and a built-in like 'start' — cannot both claim the same name.","triggerScenarios":"A plugin registers a command named e.g. \"list\" or \"adapt\" that caddy's cmd package (or another loaded plugin) already registered; the second RegisterCommand call panics during init.","commonSituations":"A custom build with several plugins where two expose the same subcommand; a plugin reusing a built-in name ('reload', 'stop', 'validate'); two versions of the same plugin accidentally linked in.","solutions":["Rename your plugin's command to something unique (vendor-prefix it, e.g. 'acme-verify')","Remove the duplicate plugin from the build","Check existing names with 'caddy help' in a build without your plugin before choosing"],"exampleFix":"// before\ncaddy.RegisterCommand(caddy.Command{Name: \"list\", ...}) // collides with built-in\n\n// after\ncaddy.RegisterCommand(caddy.Command{Name: \"myplugin-list\", ...})","handlingStrategy":"validation","validationCode":"var commandNameRegex = regexp.MustCompile(`^[a-z0-9]$|^([a-z0-9]+-?[a-z0-9]*)+[a-z0-9]$`)\nif !commandNameRegex.MatchString(name) {\n    return fmt.Errorf(\"command name %q invalid\", name)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Vendor-prefix plugin command names to avoid collisions with built-ins","Check 'caddy help' output before picking a name"],"tags":["caddy","cli","plugin","panic","naming"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}