vitessio/vitess · critical

trying to add to missing group %v

Error message

trying to add to missing group %v

What it means

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.

Source

Thrown at go/vt/vtctl/vtctl.go:770

	// `commands` => refers to `commandHelp` => refers to `PrintAllCommands` => refers to `commands`
	addCommand("Generic", command{
		name:   "Help",
		method: commandHelp,
		params: "[command name]",
		help:   "Prints the list of available commands, or help on a specific command.",
	})
}

func addCommand(groupName string, c command) {
	commandsMutex.Lock()
	defer commandsMutex.Unlock()
	for i, group := range commands {
		if group.name == groupName {
			commands[i].commands = append(commands[i].commands, c)
			return
		}
	}
	panic(fmt.Errorf("trying to add to missing group %v", groupName))
}

func addCommandGroup(groupName string) {
	commandsMutex.Lock()
	defer commandsMutex.Unlock()
	commands = append(commands, commandGroup{
		name: groupName,
	})
}

func fmtMapAwkable(m map[string]string) string {
	pairs := make([]string, len(m))
	i := 0
	for k, v := range m {
		pairs[i] = fmt.Sprintf("%v: %q", k, v)
		i++
	}
	sort.Strings(pairs)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Add (or restore) `addCommandGroup("<groupName>")` before the addCommand call in the init order.
  2. Fix the groupName string typo so it matches an existing registered group.
  3. Register the command under an existing group instead of inventing a new one.

Example fix

// before
func init() {
    addCommand("mystuff", myCommand)
}
// after
func init() {
    addCommandGroup("mystuff")
    addCommand("mystuff", myCommand)
}
Defensive patterns

Strategy: validation

Validate before calling

// Go, at development time — ensure the group exists before adding a command
func registerCommand(group string, c *command) {
    for _, g := range commands {
        if g.name == group {
            addCommand(group, c)
            return
        }
    }
    addCommandGroup(group)
    addCommand(group, c)
}

Type guard

func groupExists(groupName string) bool {
    for _, g := range commands {
        if g.name == groupName {
            return true
        }
    }
    return false
}

Try / catch

// This is a panic during init(); guard it in tests
deferr := func() {
    if r := recover(); r != nil {
        t.Fatalf("vtctl command registration panicked: %v", r)
    }
}
defer deferr()
registerTestCommands()

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/7cb617c50a79ab8b. Report an issue: GitHub.