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
- Open each profile file in the agent profiles directory and make the `id` values unique
- Check for case-only differences (Research vs research) — ids are compared case-insensitively
- Remove stale duplicate profile files left over from copies or sync tools
- 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 copying a profile file, always change the id inside, not just the filename
- Audit profile directories for case-only filename collisions after syncing from another machine
- Script generation of profiles with unique ids
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
- agent profile path is not a directory
- agent profile tools.posture= would widen permissions; use…
- agent profile cannot be empty
- agent profile must be a simple token
- agent profile may not disable approval_required
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)