Hmbown/CodeWhale · error

Fleet task ' ' metadata.coordination_contracts must contain…

Error message

Fleet task '{}' metadata.coordination_contracts must contain only strings

What it means

Each entry of metadata.coordination_contracts must be a JSON string. fleet_coordination_contracts walks the array and fails the task if any element is a non-string (object, number, boolean, null), since contracts are identifier-like strings consumed by the coordination manager.

Solutions

  1. Replace non-string entries with their string identifiers.
  2. If contracts were structured objects, extract the identifying field (e.g. `.name`) into a plain string.
  3. Fix the metadata generator's serializer to emit strings only.
  4. Trim/validate each entry after conversion — empty strings after trim are also rejected downstream.

Example fix

// before
"coordination_contracts": ["lease:db", {"name": "lock:idx"}]

// after
"coordination_contracts": ["lease:db", "lock:idx"]
Defensive patterns

Strategy: type-guard

Validate before calling

if (!contracts.every(c => typeof c === "string" && c.trim() !== "")) throw new Error("coordination_contracts must contain only non-empty strings");

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 contain only strings")) { coerce_contracts_to_strings(task); } else { throw e; } }

Prevention

When it happens

Trigger: fleet_task_to_worker_spec_with_profiles -> fleet_coordination_contracts where the array contains a non-string element, e.g. `"coordination_contracts": ["lease:db", 42]` or nested objects describing contracts.

Common situations: Generated metadata serializing contract objects instead of their names; mixed-type arrays from loosely typed config formats; copying contract definitions from another tool that used structured entries.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

    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
            );
        };
        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());
        }
    }

View on GitHub (pinned to 73e0f67d83)