Hmbown/CodeWhale · error

fleet task spec security_policy is a legacy compatibility…

Error message

fleet task spec security_policy is a legacy compatibility field, not executable Fleet identity; configure trust, secrets, approvals, sandboxing, and tool authority through Runtime policy

What it means

validate_task_spec_document (crates/tui/src/fleet/task_spec.rs:154) rejects any fleet task spec that sets `security_policy`. The field is legacy compatibility only: trust, secrets, approvals, sandboxing, and tool authority are configured through Runtime policy, not executable Fleet identity.

Solutions

  1. Delete the `security_policy` key from the task spec TOML
  2. Move the intended security configuration into Runtime policy (trust, secrets, approvals, sandboxing, tool authority)
  3. Validate again via load_task_spec_document

Example fix

# before
security_policy = "standard"
[[tasks]]
id = "build"
# after
[[tasks]]
id = "build"
# (security configured via Runtime policy)
Defensive patterns

Strategy: validation

Validate before calling

if doc.security_policy.is_some() {
    return Err("remove security_policy from task spec; configure Runtime policy instead".into());
}

Try / catch

match load_task_spec_document(path) {
    Ok(doc) => doc,
    Err(e) if e.to_string().contains("security_policy is a legacy compatibility field") => {
        eprintln!("{}: migrate to Runtime policy", path.display());
        return;
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Loading or validating a task spec document (load_task_spec_document, create_queued_run_with_descriptor) whose TOML still contains a `security_policy` key — typically a spec written for the pre-Runtime-policy schema.

Common situations: Reusing old fleet spec files from before the Runtime policy migration; docs or templates that still show security_policy; migrated specs where the field was left in place instead of deleted.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/fleet/task_spec.rs:154

        .file_stem()
        .and_then(|s| s.to_str())
        .filter(|s| !s.is_empty())
        .unwrap_or("fleet-run")
        .to_string();
    let parsed = match path.extension().and_then(|s| s.to_str()) {
        Some("toml") => toml::from_str::<FleetTaskSpecFile>(&raw)
            .with_context(|| format!("parsing TOML fleet task spec {}", path.display()))?,
        _ => serde_json::from_str::<FleetTaskSpecFile>(&raw)
            .with_context(|| format!("parsing JSON fleet task spec {}", path.display()))?,
    };
    let doc = parsed.into_document(fallback_name);
    validate_task_spec_document(&doc)?;
    Ok(doc)
}

pub fn validate_task_spec_document(doc: &FleetTaskSpecDocument) -> Result<()> {
    if doc.security_policy.is_some() {
        bail!(
            "fleet task spec security_policy is a legacy compatibility field, not executable Fleet identity; configure trust, secrets, approvals, sandboxing, and tool authority through Runtime policy"
        );
    }
    if doc.tasks.is_empty() {
        bail!("fleet task spec must include at least one task");
    }
    let mut ids = BTreeSet::new();
    for task in &doc.tasks {
        validate_fleet_identity("task id", &task.id)?;
        if !ids.insert(task.id.clone()) {
            bail!("duplicate fleet task id {}", task.id);
        }
        validate_fleet_name(&format!("task {} name", task.id), &task.name)?;
        if task.instructions.trim().is_empty() {
            bail!("fleet task {} instructions cannot be empty", task.id);
        }
        if let Some(objective) = &task.objective
            && objective.trim().is_empty()

View on GitHub (pinned to 73e0f67d83)