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
- Re-run the link command with --force to deliberately replace the existing link target.
- Delete the stale record at the links directory (<id>.toml) and link again.
- 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
- Pass --force explicitly whenever you intentionally move a source checkout.
- Keep external source paths stable; avoid renaming/moving linked directories.
- Ensure CLI ids are unique across projects to prevent record collisions.
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
- Missing profile: {}
- Could not find agent file for '{}'
- No prompt provided. Usage: f agents run {} "your prompt here
- connect is only supported for Codex sessions; use `f codex c
- runtime helpers are only supported for Codex sessions; use `
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/2ffbc80402ecc068.
Report an issue: GitHub.