nikivdev/code · error

external CLI {} is already linked to {} (use --force to repl

Error message

external CLI {} is already linked to {} (use --force to replace it)

What it means

install_external_cli_link records each external CLI link as a TOML file named <id>.toml. If a record already exists for the id and its source_root differs from the new link target, it refuses to silently repoint the link unless --force is passed.

Source

Thrown at src/external_cli.rs:146

        .with_context(|| format!("failed to resolve {}", manifest_path.display()))?;
    let manifest = read_manifest(&manifest_path)?;

    let record = ExternalCliLinkRecord {
        version: LINK_RECORD_VERSION,
        id: manifest.id.clone(),
        source_root,
        manifest_path,
        installed_at: Utc::now().to_rfc3339(),
        description: manifest.description.clone(),
    };

    let links_dir = ensure_link_records_dir()?;
    let record_path = links_dir.join(format!("{}.toml", record.id));

    if record_path.is_file() {
        let existing = read_link_record(&record_path)?;
        if !same_link_target(&existing, &record) && !force {
            bail!(
                "external CLI {} is already linked to {} (use --force to replace it)",
                record.id,
                existing.source_root.display()
            );
        }
    }

    let content = toml::to_string_pretty(&record)
        .with_context(|| format!("failed to serialize {}", record.id))?;
    fs::write(&record_path, content)
        .with_context(|| format!("failed to write {}", record_path.display()))?;

    resolved_from_link_record(&record, Some(record_path))
}

pub fn command_for_external_cli<I, S>(
    id: &str,
    args: I,

View on GitHub (pinned to a747e741ae)

Solutions

  1. Re-run the link command with --force to deliberately replace the existing link target.
  2. Delete the stale record at the links directory (<id>.toml) and link again.
  3. Use a different id if the two externals are genuinely distinct.

Example fix

// before
install_external_cli_link(&record, false)?;
// after (intentional re-link)
install_external_cli_link(&record, true)?; // equivalent of --force
Defensive patterns

Strategy: validation

Validate before calling

// Read the existing record before linking
let existing = read_link_record(&links_dir.join(format!("{}.toml", record.id)));
if let Ok(rec) = &existing {
    if rec.source_root != record.source_root && !force {
        return Err(anyhow!("{} already linked to {}; pass force to replace", record.id, rec.source_root.display()));
    }
}
install_external_cli_link(&record, force)?;

Type guard

fn link_target_matches(existing: &LinkRecord, desired: &LinkRecord) -> bool {
    same_link_target(existing, desired)
}

Try / catch

match install_external_cli_link(&record, false) {
    Err(e) if e.to_string().contains("already linked") => {
        eprintln!("Re-link intentionally with --force, or remove the stale record");
    }
    r => r?,
}

Prevention

When it happens

Trigger: Linking an external CLI id that is already linked to a different source_root with force=false; re-pointing an existing link after moving the source checkout; id collision between two different externals.

Common situations: Moving or renaming the external's source directory then re-running the link command; rebuilding links after a config change; two projects deriving the same CLI id.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/2ffbc80402ecc068. Report an issue: GitHub.