Hmbown/CodeWhale · error

duplicate agent profile id

Error message

duplicate agent profile id {}

What it means

When loading agent profiles from a directory, the loader collects profile ids into a case-insensitive BTreeSet; if two profile files produce the same id (ignoring case) the loader bails instead of letting a later file silently shadow an earlier one. Agent profile ids must be unique per directory.

Solutions

  1. Open each profile file in the agent profiles directory and make the `id` values unique
  2. Check for case-only differences (Research vs research) — ids are compared case-insensitively
  3. Remove stale duplicate profile files left over from copies or sync tools
  4. If the duplicate is intentional per-environment, split profiles across different directories

Example fix

// before: research.toml has id = "Research", copied file research-2.toml has id = "research"
// after
// research.toml:  id = "research"
// research-2.toml: id = "research-2"
Defensive patterns

Strategy: validation

Validate before calling

let mut seen = std::collections::BTreeSet::new();
for path in agent_profile_paths(dir)? {
    let profile = load_agent_profile_file(&path)?;
    if !seen.insert(profile.id.to_ascii_lowercase()) {
        eprintln!("duplicate profile id: {}", profile.id);
    }
}

Try / catch

match result {
    Err(e) if e.to_string().starts_with("duplicate agent profile id") => {
        let id = /* extract id from message */;
        eprintln!("fix or remove a duplicate profile with id {id}");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling load_agent_profiles_from_dir (directly or via load_workspace_agent_profiles) on a directory containing two files that define profiles with ids differing only by case (e.g. `Research.toml` and `research.toml`) or identical ids across files.

Common situations: Duplicating a profile file and renaming only the filename, not the `id` field inside; copying profiles between machines so the same id exists in two files; a fresh profile created with a filename that collides case-insensitively with an existing one on a case-insensitive filesystem.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/d4ee1a0f2db1ef73. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/fleet/profile.rs:348

pub fn load_agent_profile_identities_from_dir(
    dir: impl AsRef<Path>,
) -> Result<Vec<AgentProfileIdentity>> {
    let dir = dir.as_ref();
    agent_profile_paths(dir)?
        .into_iter()
        .map(|path| load_agent_profile_identity_file(&path))
        .collect()
}

pub fn load_agent_profiles_from_dir(dir: impl AsRef<Path>) -> Result<Vec<AgentProfile>> {
    let dir = dir.as_ref();
    let mut profiles = Vec::new();
    let mut seen = BTreeSet::new();
    for path in agent_profile_paths(dir)? {
        let profile = load_agent_profile_file(&path)?;
        if !seen.insert(profile.id.to_ascii_lowercase()) {
            bail!("duplicate agent profile id {}", profile.id);
        }
        profiles.push(profile);
    }
    Ok(profiles)
}

fn agent_profile_paths(dir: &Path) -> Result<Vec<PathBuf>> {
    if !dir.exists() {
        return Ok(Vec::new());
    }
    if !dir.is_dir() {
        bail!("agent profile path {} is not a directory", dir.display());
    }

    let mut paths = std::fs::read_dir(dir)
        .with_context(|| format!("reading agent profile dir {}", dir.display()))?
        .collect::<std::io::Result<Vec<_>>>()
        .with_context(|| format!("reading agent profile entries in {}", dir.display()))?

View on GitHub (pinned to 73e0f67d83)