Hmbown/CodeWhale · error · anyhow::Error

Fleet authority mismatch at the spawn boundary: the receipt…

Error message

Fleet authority mismatch at the spawn boundary: the receipt names {key}=`{expected_value}` but the child would be constructed with `{actual}`. Refusing the spawn — a Fleet ceiling that does not reach the runtime is not a ceiling.

What it means

After parsing the Fleet authority fingerprint, the spawn boundary re-derives the actual ceilings (depth, allowed/denied tools) the child would be constructed with and compares each against the receipt. Any mismatch aborts the spawn, because a Fleet ceiling recorded in the receipt that does not reach the runtime is not an enforced ceiling.

Solutions

  1. Re-issue the Fleet authority receipt after changing depth or tool policy so it matches the runtime envelope
  2. Align the child's constructed depth/allow/deny values with the receipt instead of changing them ad hoc
  3. Check which config layer is overriding the inherited values and remove the conflicting override
  4. Log both the receipt fields and actual fields to identify exactly which key mismatched (the error names it)

Example fix

// before: envelope drifts from receipt
let child = build_child(depth = 3, allow = &["read"]);
// after: derive envelope from the same authority values
let child = build_child(depth = receipt_depth, allow = &receipt_allow);
Defensive patterns

Strategy: validation

Validate before calling

let receipt_depth: u32 = fields["depth"].parse()?;
if constructed_depth != receipt_depth {
    return Err("child envelope must be built from receipt values".into());
}

Try / catch

match spawn_child(&receipt, &input) {
    Err(e) if e.to_string().contains("Fleet authority mismatch") => {
        // named key tells you which field drifted; rebuild from receipt
        let child = build_child_from_receipt(&receipt)?;
        child.run(&input)
    }
    other => other,
}

Prevention

When it happens

Trigger: Spawning a sub-agent where the receipt's depth, allow-list, or deny-list differs from the runtime envelope actually constructed — e.g. the receipt says depth=2 but the child would be built with depth=3, or the receipt's disallowed_tools disagrees with the runtime's deny set.

Common situations: A parent edited the child's tool list after the receipt was issued, an inherited budget/depth was changed by config while the receipt pinned the old values, or two components disagree about which settings define the child envelope.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/tools/subagent/mod.rs:11049

    let actual_write = input
        .get("write_authority")
        .and_then(Value::as_str)
        .unwrap_or("read_only");
    let actual_depth = input
        .get("max_depth")
        .and_then(Value::as_u64)
        .map(|depth| depth.to_string())
        .unwrap_or_default();

    for (key, actual) in [
        ("write", actual_write.to_string()),
        ("depth", actual_depth),
        ("allow", actual_allow),
        ("deny", listed("disallowed_tools")),
    ] {
        let expected_value = fields.get(key).copied().unwrap_or_default();
        if expected_value != actual {
            return Err(anyhow!(
                "Fleet authority mismatch at the spawn boundary: the receipt names {key}=`{expected_value}` \
                 but the child would be constructed with `{actual}`. Refusing the spawn — a Fleet \
                 ceiling that does not reach the runtime is not a ceiling."
            ));
        }
    }
    Ok(())
}

// === Sub-agent Execution ===

/// Build the system prompt for a sub-agent.
///
/// Starts with the per-type prompt (`FleetRole::system_prompt`) and
/// appends a one-line role overlay when `assignment.role` is set. The
/// full role library — TOML overlays from `~/.deepseek/roles/`, the
/// `/roles` slash command, model overrides per role — lands in 0.6.7.
/// For 0.6.6 we just don't drop the role on the floor: the model sees

View on GitHub (pinned to 73e0f67d83)