Hmbown/CodeWhale · error

fleet {field} must be one printable line no longer than {MAX

Error message

fleet {field} must be one printable line no longer than {MAX_FLEET_NAME_BYTES} bytes

What it means

validate_fleet_name bounds task and worker names to one printable line: at most MAX_FLEET_NAME_BYTES (256) bytes and no control characters (char::is_control catches newlines, tabs, and other control bytes). Long-form or multi-line content belongs in instructions/objective, not the name.

Source

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

fn validate_fleet_identity(field: &str, value: &str) -> Result<()> {
    if value.is_empty() {
        bail!("fleet {field} cannot be empty");
    }
    if value.len() > MAX_FLEET_ID_BYTES || !value.chars().all(is_worker_token_char) {
        bail!(
            "fleet {field} must be a simple ASCII token no longer than {MAX_FLEET_ID_BYTES} bytes"
        );
    }
    Ok(())
}

fn validate_fleet_name(field: &str, value: &str) -> Result<()> {
    if value.trim().is_empty() {
        bail!("fleet {field} cannot be empty");
    }
    if value.len() > MAX_FLEET_NAME_BYTES || value.chars().any(char::is_control) {
        bail!(
            "fleet {field} must be one printable line no longer than {MAX_FLEET_NAME_BYTES} bytes"
        );
    }
    Ok(())
}

fn validate_worker_profile(task_id: &str, worker: Option<&FleetTaskWorkerProfile>) -> Result<()> {
    let Some(worker) = worker else {
        return Ok(());
    };
    validate_worker_token(
        task_id,
        "worker.agent_profile",
        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())?;

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Collapse the name to a single printable line of 256 bytes or fewer
  2. Move detail and multi-line content into instructions (or objective)
  3. Sanitize templated names by stripping control characters at generation time

Example fix

// before
{ "id": "t1", "name": "Fix login\nthen run tests", "instructions": "..." }

// after
{ "id": "t1", "name": "Fix login and run tests", "instructions": "Fix the login flow, then run the test suite." }
Defensive patterns

Strategy: validation

Validate before calling

const MAX_FLEET_NAME_BYTES: usize = 256;
fn is_fleet_name(s: &str) -> bool {
    !s.trim().is_empty()
        && s.len() <= MAX_FLEET_NAME_BYTES
        && !s.chars().any(char::is_control)
}

Type guard

function isOneLineName(name: string): boolean {
  return name.trim().length > 0 && name.length <= 256 &&
    !/[\u0000-\u001f]/.test(name);
}

Try / catch

if let Err(err) = load_task_spec_document(&path) {
    if err.to_string().contains("one printable line") {
        eprintln!("{path:?}: names must be a single line <=256 bytes; move detail to instructions");
    }
    return Err(err);
}

Prevention

When it happens

Trigger: name = "line1\nline2" (embedded newline from pasting multi-line text), a name containing a tab, or a name longer than 256 bytes.

Common situations: Pasting a paragraph into the name field; templates inserting raw user text with line breaks; auto-generated names that concatenate many attributes until they exceed the limit.

Related errors


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