Hmbown/CodeWhale · error

Fleet task ' ' metadata.coordination_contracts must be an…

Error message

Fleet task '{}' metadata.coordination_contracts must be an array of strings

What it means

fleet_coordination_contracts reads task_spec.metadata["coordination_contracts"]; when the key exists but its value is not a JSON array, the task cannot form a coordination claim and the spec build fails. Contracts must be an array of strings (bounded at 16 entries).

Solutions

  1. Wrap the value in an array: `"coordination_contracts": ["contract-a"]`.
  2. Remove the metadata key entirely if no contracts are needed (missing key is valid and returns an empty vec).
  3. Fix the metadata producer to emit a JSON array of strings.
  4. Validate run JSON before submission so malformed metadata is caught early.

Example fix

// before
"metadata": { "coordination_contracts": "lease:db-migration" }

// after
"metadata": { "coordination_contracts": ["lease:db-migration"] }
Defensive patterns

Strategy: type-guard

Validate before calling

const contracts = run.metadata?.coordination_contracts;
if (contracts !== undefined && !Array.isArray(contracts)) throw new Error("coordination_contracts must be an array");

Type guard

function isStringArray(v) { return Array.isArray(v) && v.every(x => typeof x === "string"); }

Try / catch

try { build_spec(task) } catch (e) { if (String(e).includes("must be an array of strings")) { fix_metadata_shape(task); } else { throw e; } }

Prevention

When it happens

Trigger: fleet_task_to_worker_spec_with_profiles -> fleet_coordination_contracts where metadata contains `coordination_contracts` as a string (e.g. `"contract-a"`), object, or number instead of an array.

Common situations: Hand-editing fleet run JSON and writing the contract as a single string instead of a one-element array; YAML/JSON type confusion where a quoted string was intended as a list; programmatic metadata writers storing the field under the wrong shape.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

                    path.display()
                );
            }
            value => segments.push(value),
        }
    }
    Ok(if segments.is_empty() {
        ".".to_string()
    } else {
        segments.join("/")
    })
}

fn fleet_coordination_contracts(task_spec: &FleetTaskSpec) -> Result<Vec<String>> {
    let Some(value) = task_spec.metadata.get("coordination_contracts") else {
        return Ok(Vec::new());
    };
    let Some(values) = value.as_array() else {
        bail!(
            "Fleet task '{}' metadata.coordination_contracts must be an array of strings",
            task_spec.id
        );
    };
    if values.len() > 16 {
        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
            );
        };

View on GitHub (pinned to 73e0f67d83)