larksuite/cli · error

command set %d for domain %q has no commands

Error message

command set %d for domain %q has no commands

What it means

CompileSets requires every command set to declare at least one command. A set whose Commands slice is empty cannot contribute a runnable command path, so compilation fails with the set index and its domain name. It fails atomically — no partial compilation result is returned.

Source

Thrown at internal/commandhost/compile.go:45

	if len(sets) == 0 {
		return nil, nil
	}

	builtins := shortcuts.AllShortcuts()
	paths := make(map[string]string, len(builtins))
	for _, shortcut := range builtins {
		paths[shortcut.Service+" "+shortcut.Command] = "built-in command"
	}
	existingDomains := businessDomains()

	compiled := make([]common.Shortcut, 0)
	for setIndex, set := range sets {
		domain := command.InspectDomain(set.Domain)
		if err := validateDomain(domain, existingDomains); err != nil {
			return nil, fmt.Errorf("command set %d: %w", setIndex+1, err)
		}
		if len(set.Commands) == 0 {
			return nil, fmt.Errorf("command set %d for domain %q has no commands", setIndex+1, domain.Name)
		}
		for commandIndex, declaration := range set.Commands {
			definition := command.InspectCommand(declaration)
			if string(definition.Metadata.Service) != domain.Name {
				return nil, fmt.Errorf("command set %d command %d: Metadata.Service %q does not match domain %q",
					setIndex+1, commandIndex+1, definition.Metadata.Service, domain.Name)
			}
			shortcutPath := string(definition.Metadata.Service) + " " + definition.Metadata.Command
			if owner, duplicate := paths[shortcutPath]; duplicate {
				return nil, fmt.Errorf("command set %d command %d: command path %q conflicts with %s",
					setIndex+1, commandIndex+1, shortcutPath, owner)
			}
			shortcut, err := compileCommand(definition)
			if err != nil {
				return nil, fmt.Errorf("command set %d command %d (%s): %w", setIndex+1, commandIndex+1, shortcutPath, err)
			}
			paths[shortcutPath] = fmt.Sprintf("command set %d command %d", setIndex+1, commandIndex+1)
			compiled = append(compiled, shortcut)

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Add at least one command declaration to the set's Commands slice
  2. Remove the set registration entirely if the domain has no commands yet
  3. Check whether build-tag or config filtering emptied the slice unintentionally

Example fix

// before
sets := []common.ShortcutSet{{Domain: myDomain}} // no commands
// after
sets := []common.ShortcutSet{{Domain: myDomain, Commands: []common.CommandDeclaration{myCmd}}}
Defensive patterns

Strategy: validation

Validate before calling

// before CompileSets:
for i, s := range sets {
    if len(s.Commands) == 0 { return fmt.Errorf("set %d (%v) declares no commands", i+1, s.Domain) }
}

Try / catch

if _, err := commandhost.CompileSets(sets); err != nil {
    return fmt.Errorf("shortcut registration failed: %w", err) // surfaces set index + domain
}

Prevention

When it happens

Trigger: Registering common.ShortcutSet with a valid Domain but zero entries in Commands; building the slice conditionally such that all commands are filtered out before CompileSets runs.

Common situations: A new shortcuts package stubbed with an empty Shortcuts() list; feature-flag filtering that removes every command; refactoring that renamed command constructors leaving the slice empty.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/ca2d26fb52f93e86. Report an issue: GitHub.