Hmbown/CodeWhale · error

Fleet task ' ' coordination contracts must be one non-empty…

Error message

Fleet task '{}' coordination contracts must be one non-empty line of at most 128 characters

What it means

Fleet coordination contract strings attached to a task must be a single non-empty line of at most 128 characters with no NUL, CR, or LF characters. The library validates each trimmed contract value in fleet_coordination_contracts before storing it, because contracts are used as identifiers/labels across worker specs and must be safe for one-line contexts. This bail fires when any contract string for the task violates those bounds.

Solutions

  1. Trim and inspect every entry of the task's coordination_contracts before building the spec; remove or split any entry over 128 chars.
  2. Strip newlines/NUL characters, or reject multi-line contracts at config-load time.
  3. If a contract needs more content, use an external document referenced by a short contract key.
  4. Fail loud at configuration parse time so bad contracts never reach the runtime.

Example fix

// before
contracts: vec![format!("long contract {}", "x".repeat(200))]
// after
contracts: vec!["short-contract-key".to_string()]
Defensive patterns

Strategy: validation

Validate before calling

fn valid_contract(s: &str) -> bool {
    let s = s.trim();
    !s.is_empty()
        && s.chars().count() <= 128
        && !s.chars().any(|c| matches!(c, '\0' | '\r' | '\n'))
}

Type guard

fn as_contract(s: &str) -> Option<&str> {
    let t = s.trim();
    (!t.is_empty() && t.chars().count() <= 128 && !t.contains(['\0','\r','\n'])).then_some(t)
}

Try / catch

match build_worker_spec(task) {
    Err(e) if e.to_string().contains("coordination contracts") => warn!("task {}: fix contract strings (one line, <=128 chars)", task.id),
    Err(e) => return Err(e),
    Ok(spec) => spec,
}

Prevention

When it happens

Trigger: Calling fleet_task_to_worker_spec_with_profiles (or the validate path) with a task whose coordination_contracts contains an empty/whitespace-only entry, an entry longer than 128 characters (chars, not bytes), or an entry containing '\0', '\r', or '\n' (e.g. a multi-line pasted contract).

Common situations: Pasting a multi-line coordination contract from a shell or document; auto-generated contract names that exceed 128 chars; an empty contracts list serialized as a list with one blank string; CRLF line endings embedded in a contract from a Windows config file.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/fleet/worker_runtime.rs:616

        bail!(
            "Fleet task '{}' metadata.coordination_contracts accepts at most 16 entries",
            task_spec.id
        );
    }
    let mut contracts = Vec::new();
    for value in values {
        let Some(value) = value.as_str() else {
            bail!(
                "Fleet task '{}' metadata.coordination_contracts must contain only strings",
                task_spec.id
            );
        };
        let value = value.trim();
        if value.is_empty()
            || value.chars().count() > 128
            || value.chars().any(|ch| matches!(ch, '\0' | '\r' | '\n'))
        {
            bail!(
                "Fleet task '{}' coordination contracts must be one non-empty line of at most 128 characters",
                task_spec.id
            );
        }
        if !contracts.iter().any(|contract| contract == value) {
            contracts.push(value.to_string());
        }
    }
    Ok(contracts)
}

/// Mint a [`FleetResolvedRoute`] snapshot for a fleet task (#3154).
///
/// This calls the existing hermetic resolver bridge
/// ([`resolve_route_candidate`]) so the persisted route reflects the same
/// resolution semantics the runtime would use, then records only non-sensitive
/// shape (provider id/kind, model ids, protocol) combined with the already
/// computed effective role/loadout/model-class intent. `source` is

View on GitHub (pinned to 73e0f67d83)