chenhg5/cc-connect · error

command %q not found

Error message

command %q not found

What it means

RemoveCommand returns this error when no command with the given name exists in the parsed config's Commands list. The config loaded and parsed fine; the requested name simply is not registered. This is a lookup miss, not an I/O or parse failure.

Source

Thrown at config/config.go:1729

	data, err := os.ReadFile(ConfigPath)
	if err != nil {
		return fmt.Errorf("read config: %w", err)
	}
	cfg := &Config{}
	if err := toml.Unmarshal(data, cfg); err != nil {
		return fmt.Errorf("parse config: %w", err)
	}
	found := false
	var remaining []CommandConfig
	for _, c := range cfg.Commands {
		if c.Name == name {
			found = true
		} else {
			remaining = append(remaining, c)
		}
	}
	if !found {
		return fmt.Errorf("command %q not found", name)
	}
	cfg.Commands = remaining
	return saveConfig(cfg)
}

// AddAlias adds a global alias and persists to config.
func AddAlias(alias AliasConfig) error {
	configMu.Lock()
	defer configMu.Unlock()
	if ConfigPath == "" {
		return fmt.Errorf("config path not set")
	}
	data, err := os.ReadFile(ConfigPath)
	if err != nil {
		return fmt.Errorf("read config: %w", err)
	}
	cfg := &Config{}
	if err := toml.Unmarshal(data, cfg); err != nil {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. List existing global commands (or read config.toml) and confirm the exact name before removing.
  2. Match names exactly, normalizing case/whitespace if your tool trims inputs.
  3. Treat 'not found' as success in idempotent cleanup scripts.
  4. If the command lives in a project section, use the project-scoped removal API instead of the global one.

Example fix

// before
config.RemoveCommand(strings.TrimSpace(userInput)) // typos slip through

// after
names, _ := config.ListCommands()
if !slices.Contains(names, name) {
    return nil // idempotent
}
if err := config.RemoveCommand(name); err != nil { return err }
Defensive patterns

Strategy: fallback

Validate before calling

cmds, _ := config.ListCommands()
found := slices.ContainsFunc(cmds, func(c config.CommandConfig) bool { return c.Name == name })
if !found {
    return nil // already gone; idempotent success
}

Try / catch

err := config.RemoveCommand(name)
if err != nil && strings.Contains(err.Error(), "not found") {
    return nil // idempotent: command already absent
}
if err != nil {
    return err
}

Prevention

When it happens

Trigger: Calling config.RemoveCommand(name) where name matches no entry in cfg.Commands during the loop over cfg.Commands (config/config.go:1729), leaving found == false.

Common situations: Typo in the command name; case-sensitivity mismatch ('Deploy' vs 'deploy'); removing a command that was already removed (double-run of cleanup scripts); name defined per-project instead of globally, so the global list lookup misses it.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/c061380dc34ac81e. Report an issue: GitHub.