Hmbown/CodeWhale · error

agent profile path {} is not a directory

Error message

agent profile path {} is not a directory

What it means

agent_profile_paths expects the configured profiles location to be a directory of TOML files. The path exists but is a regular file, so read_dir cannot proceed and the loader bails with the offending path. A missing path is fine (empty profile set); a file is not.

Source

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

    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()))?
        .into_iter()
        .map(|entry| entry.path())
        .filter(|path| path.extension().and_then(|value| value.to_str()) == Some("toml"))
        .collect::<Vec<_>>();
    paths.sort();
    Ok(paths)
}

fn load_agent_profile_identity_file(path: &Path) -> Result<AgentProfileIdentity> {
    let raw = std::fs::read_to_string(path)
        .with_context(|| format!("reading agent profile identity {}", path.display()))?;
    let parsed: AgentProfileIdentityToml = toml::from_str(&raw)

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Point the setting at the directory containing the profile TOMLs, not at a file
  2. If you only have one profile file, put it in a directory and reference the directory
  3. Verify with ls -ld that the path resolves to a directory

Example fix

# before
[fleet]
agent_profiles = "~/.config/codewhale/profiles/default.toml"

# after
[fleet]
agent_profiles = "~/.config/codewhale/profiles"
Defensive patterns

Strategy: validation

Validate before calling

use std::path::Path;

fn profiles_path_is_dir(path: &Path) -> bool {
    !path.exists() || path.is_dir() // missing is fine; a file is not
}

Try / catch

if let Err(err) = load_agent_profiles_from_dir(&configured) {
    if err.to_string().contains("is not a directory") {
        eprintln!("point the agent profiles setting at a directory of TOML files");
    }
    return Err(err.into());
}

Prevention

When it happens

Trigger: Configuring the agent profiles setting to a single TOML file path instead of its containing directory.

Common situations: Users pointing the setting directly at profiles/default.toml; migrating from a single-file profile config to the directory layout; a symlink pointing at a file.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/56ea8d0247701837. Report an issue: GitHub.