chenhg5/cc-connect · error

command already exists

Error message

command %q already exists

What it means

AddCommand rejects the operation because a command with the same name already exists in the global commands list. This is a deliberate duplicate-name guard, not an I/O failure. Pick a different name or remove the existing command first.

Solutions

  1. Check existing commands first (config listing API or read config.toml) and skip the add if the name exists for idempotency.
  2. Use a different, unique name for the new command.
  3. Remove the existing command with config.RemoveCommand(name) if it should be replaced, then re-add.
  4. Normalize (trim/lowercase) names before comparing to avoid near-duplicate collisions.

Example fix

// before
config.AddCommand(cmd) // errors if name exists

// after
if err := config.AddCommand(cmd); err != nil {
    if strings.Contains(err.Error(), "already exists") {
        return nil // idempotent skip
    }
    return err
}
Defensive patterns

Strategy: validation

Validate before calling

cmds, err := config.ListCommands()
if err != nil {
    return err
}
for _, c := range cmds {
    if c.Name == cmd.Name {
        return fmt.Errorf("command %q exists; choose another name", cmd.Name)
    }
}

Try / catch

err := config.AddCommand(cmd)
if err != nil && strings.Contains(err.Error(), "already exists") {
    return nil // treat as idempotent success
}

Prevention

When it happens

Trigger: Calling config.AddCommand(cmd) where cmd.Name equals the Name field of any entry already in cfg.Commands after parsing the config (config/config.go:1697).

Common situations: Re-running an install/setup script that adds the same custom command twice; idempotency-ignorant tooling; user re-adding a command they forgot exists; case/whitespace variants being auto-trimmed to a colliding name.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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

Appendix: source

Thrown at config/config.go:1697

// AddCommand adds a global custom command and persists to config.
func AddCommand(cmd CommandConfig) 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 {
		return fmt.Errorf("parse config: %w", err)
	}
	for _, c := range cfg.Commands {
		if c.Name == cmd.Name {
			return fmt.Errorf("command %q already exists", cmd.Name)
		}
	}
	cfg.Commands = append(cfg.Commands, cmd)
	return saveConfig(cfg)
}

// RemoveCommand removes a global custom command and persists to config.
func RemoveCommand(name string) 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{}

View on GitHub (pinned to 4000b2338a)