Hmbown/CodeWhale · error
duplicate fleet task id
Error message
duplicate fleet task id {} What it means
Task ids within a fleet task spec must be unique. validate_task_spec_document (crates/tui/src/fleet/task_spec.rs:165) tracks ids in a BTreeSet and bails on the first repeated task id, because ids identify tasks and workers within a run.
Solutions
- Give each [[tasks]] block a distinct id
- If tasks were meant to be variants, append a suffix (build-1, build-2)
- Search the spec for duplicate `id = "..."` values under [tasks]
Example fix
# before [[tasks]] id = "build" [[tasks]] id = "build" # after [[tasks]] id = "build" [[tasks]] id = "test"
Defensive patterns
Strategy: validation
Validate before calling
let mut ids = std::collections::BTreeSet::new();
for t in &doc.tasks {
if !ids.insert(t.id.clone()) {
return Err(format!("duplicate task id: {}", t.id));
}
} Try / catch
match load_task_spec_document(path) {
Ok(doc) => doc,
Err(e) if e.to_string().contains("duplicate fleet task id") => {
eprintln!("{}: rename one of the duplicate task ids", path.display());
return;
}
Err(e) => return Err(e),
} Prevention
- Use id templates that include an index for generated task blocks
- Check for duplicate ids after editing spec files
- Keep a lint step that dedupes task ids in CI
When it happens
Trigger: A spec document contains two or more [[tasks]] blocks with the same `id`; detected during load_task_spec_document or create_queued_run_with_descriptor.
Common situations: Copy-pasting a task block to create a variant and forgetting to change the id; generated specs where an id template does not include an index.
Related errors
- duplicate fleet worker id
- agent profile provider cannot be empty
- agent profile provider must be a simple provider id
- fleet cannot be empty
- Fleet task ' ' coordination contracts must be one non-empty…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/a8875ad1875a4f44.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/fleet/task_spec.rs:165
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()
{
bail!("fleet task {} objective cannot be empty", task.id);
}
validate_worker_profile(&task.id, task.worker.as_ref())?;
if task
.metadata
.contains_key(super::worker_runtime::FROZEN_FLEET_MEMBER_METADATA_KEY)
{
bail!(
"fleet task {} metadata key {} is reserved for the durable Runtime selection receipt",
task.id,View on GitHub (pinned to 73e0f67d83)