larksuite/cli · error

command set %d command %d: command path %q conflicts with %s

Error message

command set %d command %d: command path %q conflicts with %s

What it means

CompileSets builds the flat list of Shortcut commands from registered command sets. Every compiled command must own a unique 'service command' path; when a second definition produces the same path as one already registered, compilation aborts so an ambiguous route can never reach dispatch.

Source

Thrown at internal/commandhost/compile.go:55

	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)
		}
	}
	return compiled, nil
}

// ValidateDeclaration compiles one declaration through the production compiler
// and discards the result. A business test harness calls it so a wrong tag,
// Shape or relation fails in the unit test rather than at CLI startup: executing
// hooks directly exercises none of the compiler's contract checks, which is the
// gap that let a green test ship a command that cannot mount.

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Rename the duplicate definition's Metadata.Command so the path is unique
  2. Change Metadata.Service on one of the conflicting definitions to a distinct domain
  3. Search all command set registrations for the path printed in the error and remove the stale duplicate

Example fix

// before
Metadata: command.Metadata{Service: "doc", Command: "create"}
// second set
Metadata: command.Metadata{Service: "doc", Command: "create"}
// after
Metadata: command.Metadata{Service: "doc", Command: "create"}
Metadata: command.Metadata{Service: "doc", Command: "create-from-template"}
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]bool{}
for _, def := range defs {
    p := string(def.Metadata.Service) + " " + def.Metadata.Command
    if seen[p] { return fmt.Errorf("duplicate command path %q", p) }
    seen[p] = true
}

Try / catch

compiled, err := commandhost.CompileSets(sets)
if err != nil && strings.Contains(err.Error(), "conflicts with") {
    return fmt.Errorf("fix duplicate shortcut registration: %w", err)
}

Prevention

When it happens

Trigger: Registering two HostDefinitions in (possibly different) command sets whose Metadata.Service plus Metadata.Command collide, e.g. two shortcuts both named 'doc create' or a service value that duplicates a core command's path.

Common situations: Copy-pasting an existing shortcut definition and forgetting to rename it; a plugin/extension contributing a set that overlaps a built-in domain; renaming Metadata.Command in one place but leaving a stale duplicate.

Related errors


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