Hmbown/CodeWhale · error

fleet task {task_id} worker.model cannot be empty

Error message

fleet task {task_id} worker.model cannot be empty

What it means

validate_worker_model checks a task's optional worker.model override. If the field is present it must be non-blank after trimming; an empty or whitespace-only model is rejected rather than treated as "use the default".

Source

Thrown at crates/tui/src/fleet/task_spec.rs:213

    if trimmed != value || !trimmed.chars().all(is_worker_token_char) {
        bail!(
            "fleet task {task_id} {field} must be a simple token, not a path or provider/model id"
        );
    }
    Ok(())
}

fn is_worker_token_char(ch: char) -> bool {
    ch.is_ascii_alphanumeric() || matches!(ch, '-' | '_' | '.')
}

fn validate_worker_model(task_id: &str, value: Option<&str>) -> Result<()> {
    let Some(value) = value else {
        return Ok(());
    };
    let trimmed = value.trim();
    if trimmed.is_empty() {
        bail!("fleet task {task_id} worker.model cannot be empty");
    }
    if trimmed != value
        || !trimmed
            .chars()
            .all(|ch| ch.is_ascii_graphic() && !matches!(ch, '=' | '\'' | '"'))
    {
        bail!(
            "fleet task {task_id} worker.model must be a visible model id without whitespace or secrets"
        );
    }
    Ok(())
}

#[allow(clippy::too_many_arguments)]
pub fn write_fleet_artifact_ref(
    workspace: &Path,
    run_id: &FleetRunId,
    task_id: &str,

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Delete the blank worker.model key to fall back to the profile's model
  2. Or set the intended model id, e.g. "worker": { "model": "gpt-4o" }
  3. Configure your serializer to skip empty optional fields when emitting specs

Example fix

// before
{ "id": "t1", "instructions": "...", "worker": { "model": "" } }

// after
{ "id": "t1", "instructions": "...", "worker": { "model": "gpt-4o" } }
Defensive patterns

Strategy: validation

Validate before calling

fn worker_model_ok(value: Option<&str>) -> bool {
    value.map_or(true, |v| !v.trim().is_empty())
}

Type guard

function optionalModelOk(v: string | undefined): boolean {
  return v === undefined || v.trim().length > 0;
}

Try / catch

if let Err(err) = load_task_spec_document(&path) {
    if err.to_string().contains("worker.model cannot be empty") {
        eprintln!("{path:?}: blank worker.model - set a model id or drop the key");
    }
    return Err(err);
}

Prevention

When it happens

Trigger: A task with "worker": { "model": "" } or "model": " ". Omitting the key passes - the worker then uses the profile-resolved model.

Common situations: Templates that always emit worker.model; clearing a per-task model override by emptying the string instead of deleting the key; generators writing empty strings for unset optionals.

Related errors


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