Hmbown/CodeWhale · error

agent profile {} {field} cannot be empty

Error message

agent profile {} {field} cannot be empty

What it means

validate_agent_profile_token guards the id/name and base_role/role_hint fields of an agent profile. The effective id is id, else name, else the file stem. If that value is empty after trimming, load fails so the roster never contains a blank identity.

Source

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

            bail!(
                "agent profile {} may not request trust=true",
                path.display()
            );
        }
        if permissions.approval_required == Some(false) {
            bail!(
                "agent profile {} may not disable approval_required",
                path.display()
            );
        }
    }
    Ok(())
}

fn validate_agent_profile_token(path: &Path, field: &str, value: &str) -> Result<()> {
    let trimmed = value.trim();
    if trimmed.is_empty() {
        bail!("agent profile {} {field} cannot be empty", path.display());
    }
    if trimmed != value || !trimmed.chars().all(is_agent_profile_token_char) {
        bail!(
            "agent profile {} {field} must be a simple token",
            path.display()
        );
    }
    Ok(())
}

fn validate_agent_profile_model_hint(path: &Path, value: Option<&str>) -> Result<()> {
    let Some(value) = value else {
        return Ok(());
    };
    if !is_model_hint(value) {
        bail!(
            "agent profile {} model must be a visible model id without whitespace or secrets",
            path.display()

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Set id = "<slug>" to a non-empty token in the profile TOML named in the error
  2. If the id comes from name or the filename, give the file a real stem (rename .toml to scout.toml)
  3. Check the path in the error message - it identifies the exact failing file

Example fix

# before (.codewhale/agents/.toml)
name = ""

# after (.codewhale/agents/scout.toml)
id = "scout"
Defensive patterns

Strategy: validation

Validate before calling

fn effective_profile_id(id: Option<&str>, name: Option<&str>, stem: &str) -> bool {
    let effective = [id, name].into_iter().flatten().find(|v| !v.trim().is_empty());
    effective.map(|v| !v.trim().is_empty()).unwrap_or(!stem.trim().is_empty())
}

Type guard

fn is_profile_token(s: &str) -> bool {
    let t = s.trim();
    !t.is_empty() && t == s
        && t.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '-' | '_' | '.'))
}

Try / catch

match load_agent_profile_file(&path) {
    Ok(p) => Ok(p),
    Err(err) if err.to_string().contains("cannot be empty") => {
        Err(anyhow!("profile {path:?} has a blank id/name - set id or rename the file"))
    }
    Err(err) => Err(err),
}

Prevention

When it happens

Trigger: A profile whose effective id/name trims to nothing: id = "" (or name = " " with no id), or a profile file whose stem is blank (for example a file saved as .toml), which becomes the fallback id. Also fires for identity files scanned from roster directories via the same validator.

Common situations: A template profile created with a placeholder empty id; a file accidentally saved as .toml so the stem fallback is empty; generated profiles where the id field was never filled in.

Related errors


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