Hmbown/CodeWhale · error

fleet task must be one printable selector no longer than…

Error message

fleet task {task_id} {field} must be one printable selector no longer than {MAX_FLEET_NAME_BYTES} bytes

What it means

Worker selectors, when present, must be one printable line no longer than MAX_FLEET_NAME_BYTES with no leading/trailing whitespace. validate_worker_selector rejects values that were trimmed differently from the original, exceed the byte cap, or contain control characters. Selectors must be stable, canonical strings.

Solutions

  1. Trim the selector before storing it (only untrimmed values pass)
  2. Remove control characters/newlines from the selector
  3. Shorten the selector to at most MAX_FLEET_NAME_BYTES bytes

Example fix

// before
selector: Some(" gpu=true ")
// after
selector: Some("gpu=true")
Defensive patterns

Strategy: validation

Validate before calling

fn selector_format_ok(v: &str) -> bool { v.trim() == v && v.len() <= MAX_FLEET_NAME_BYTES && !v.chars().any(char::is_control) }

Type guard

fn canonical_selector(v: &str) -> Option<&str> { selector_format_ok(v).then_some(v) }

Try / catch

if let Err(e) = validate_worker_selector(task_id, "selector", value) { if e.to_string().contains("printable selector") { eprintln!("trim/control-char issue: {e}"); } }

Prevention

When it happens

Trigger: validate_worker_profile sees a selector containing surrounding whitespace (trimmed != value), a value over MAX_FLEET_NAME_BYTES, or control characters.

Common situations: Copy-pasting a selector with a trailing space or newline; multi-line label expressions; overly long selector strings.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

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

        worker.agent_profile.as_deref(),
    )?;
    validate_worker_token(task_id, "worker.loadout", worker.loadout.as_deref())?;
    validate_worker_token(task_id, "worker.model_class", worker.model_class.as_deref())?;
    validate_worker_model(task_id, worker.model.as_deref())?;
    Ok(())
}

fn validate_worker_selector(task_id: &str, field: &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} {field} cannot be empty");
    }
    if trimmed != value || value.len() > MAX_FLEET_NAME_BYTES || value.chars().any(char::is_control)
    {
        bail!(
            "fleet task {task_id} {field} must be one printable selector no longer than {MAX_FLEET_NAME_BYTES} bytes"
        );
    }
    Ok(())
}

fn validate_worker_token(task_id: &str, field: &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} {field} cannot be empty");
    }
    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"
        );

View on GitHub (pinned to 73e0f67d83)