larksuite/cli · error

command set %d command %d: Metadata.Service %q does not matc

Error message

command set %d command %d: Metadata.Service %q does not match domain %q

What it means

CompileSets enforces that each command's Metadata.Service matches its set's domain name, rejecting mismatches with both indices and values. It also derives the canonical shortcut path (Service + " " + Command) from these fields, so an inconsistency would produce wrong command paths — hence the hard check.

Source

Thrown at internal/commandhost/compile.go:50

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

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Set Metadata.Command/Metadata.Service on the declaration to match the owning domain
  2. Move the declaration into the set whose Domain equals its Metadata.Service
  3. Use the domain's exported Domain constant for Metadata.Service instead of a string literal

Example fix

// before
// in im shortcuts set
Metadata: common.Metadata{Service: "contact", Command: "chat:list"}
// after
Metadata: common.Metadata{Service: "im", Command: "chat:list"}
Defensive patterns

Strategy: validation

Validate before calling

// before CompileSets:
for i, s := range sets {
    d := command.InspectDomain(s.Domain)
    for j, c := range s.Commands {
        m := command.InspectCommand(c).Metadata
        if string(m.Service) != d.Name {
            return fmt.Errorf("set %d cmd %d: Service %q != domain %q", i+1, j+1, m.Service, d.Name)
        }
    }
}

Try / catch

if _, err := commandhost.CompileSets(sets); err != nil {
    return fmt.Errorf("shortcut registration failed: %w", err) // reports indices and both values
}

Prevention

When it happens

Trigger: Registering a command whose definition.Metadata.Service (via command.InspectCommand) differs from set.Domain, e.g. reusing a command declaration from another domain's set or editing Metadata.Service manually.

Common situations: Copy-pasting a command declaration into a different domain's shortcut set without updating Metadata.Service; renaming a domain without updating command metadata; plugin commands registered under the wrong domain set.

Related errors


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