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
- Trim and inspect every entry of the task's coordination_contracts before building the spec; remove or split any entry over 128 chars.
- Strip newlines/NUL characters, or reject multi-line contracts at config-load time.
- If a contract needs more content, use an external document referenced by a short contract key.
- 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
- Validate contract strings at config-parse time, not task-launch time
- Enforce one-line input fields in any UI that collects contracts
- Add a schema/length check in CI for fleet config fixtures
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
- agent profile provider cannot be empty
- agent profile provider must be a simple provider id
- duplicate fleet task id
- duplicate fleet worker id
- fleet cannot be empty
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` isView on GitHub (pinned to 73e0f67d83)