{"record":{"id":"7cb617c50a79ab8b","repo":"vitessio/vitess","slug":"trying-to-add-to-missing-group-v","errorCode":null,"errorMessage":"trying to add to missing group %v","messagePattern":"trying to add to missing group (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"go/vt/vtctl/vtctl.go","lineNumber":770,"sourceCode":"\t// `commands` => refers to `commandHelp` => refers to `PrintAllCommands` => refers to `commands`\n\taddCommand(\"Generic\", command{\n\t\tname:   \"Help\",\n\t\tmethod: commandHelp,\n\t\tparams: \"[command name]\",\n\t\thelp:   \"Prints the list of available commands, or help on a specific command.\",\n\t})\n}\n\nfunc addCommand(groupName string, c command) {\n\tcommandsMutex.Lock()\n\tdefer commandsMutex.Unlock()\n\tfor i, group := range commands {\n\t\tif group.name == groupName {\n\t\t\tcommands[i].commands = append(commands[i].commands, c)\n\t\t\treturn\n\t\t}\n\t}\n\tpanic(fmt.Errorf(\"trying to add to missing group %v\", groupName))\n}\n\nfunc addCommandGroup(groupName string) {\n\tcommandsMutex.Lock()\n\tdefer commandsMutex.Unlock()\n\tcommands = append(commands, commandGroup{\n\t\tname: groupName,\n\t})\n}\n\nfunc fmtMapAwkable(m map[string]string) string {\n\tpairs := make([]string, len(m))\n\ti := 0\n\tfor k, v := range m {\n\t\tpairs[i] = fmt.Sprintf(\"%v: %q\", k, v)\n\t\ti++\n\t}\n\tsort.Strings(pairs)","sourceCodeStart":752,"sourceCodeEnd":788,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtctl/vtctl.go#L752-L788","documentation":"vtctl's addCommand registers a command under a named command group by linear scan; if no group with that name exists it panics. This is an init-time programming error — the group must be created with addCommandGroup before commands are added to it.","triggerScenarios":"A developer adds a new `addCommand(\"somegroup\", ...)` call in an init() function without a matching earlier `addCommandGroup(\"somegroup\")`. Since it runs at package init, the process panics immediately at startup.","commonSituations":"Adding a new vtctl command during development and forgetting to register its group; renaming a command group in one place but not the other; merge conflicts dropping an addCommandGroup line.","solutions":["Add (or restore) `addCommandGroup(\"<groupName>\")` before the addCommand call in the init order.","Fix the groupName string typo so it matches an existing registered group.","Register the command under an existing group instead of inventing a new one."],"exampleFix":"// before\nfunc init() {\n    addCommand(\"mystuff\", myCommand)\n}\n// after\nfunc init() {\n    addCommandGroup(\"mystuff\")\n    addCommand(\"mystuff\", myCommand)\n}","handlingStrategy":"validation","validationCode":"// Go, at development time — ensure the group exists before adding a command\nfunc registerCommand(group string, c *command) {\n    for _, g := range commands {\n        if g.name == group {\n            addCommand(group, c)\n            return\n        }\n    }\n    addCommandGroup(group)\n    addCommand(group, c)\n}","typeGuard":"func groupExists(groupName string) bool {\n    for _, g := range commands {\n        if g.name == groupName {\n            return true\n        }\n    }\n    return false\n}","tryCatchPattern":"// This is a panic during init(); guard it in tests\ndeferr := func() {\n    if r := recover(); r != nil {\n        t.Fatalf(\"vtctl command registration panicked: %v\", r)\n    }\n}\ndefer deferr()\nregisterTestCommands()","preventionTips":["Always pair new addCommand calls with an addCommandGroup call earlier in the same init().","Add an init-order unit test that registers all command groups.","Search for addCommandGroup when renaming a command group."],"tags":["panic","init","cli-registry","developer-error"],"backgroundTag":"missing-registry-group","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}