{"record":{"id":"bff130af5824f4f3","repo":"Hmbown/CodeWhale","slug":"fleet-task-task-id-has-duplicate-tag-tag","errorCode":null,"errorMessage":"fleet task {task_id} has duplicate tag {tag}","messagePattern":"fleet task (.+?) has duplicate tag (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/fleet/task_spec.rs","lineNumber":371,"sourceCode":"pub fn record_verification_receipt(\n    ledger: &FleetLedger,\n    workspace: &Path,\n    input: &FleetTaskVerificationInput,\n    verification: FleetTaskVerification,\n) -> Result<FleetReceipt> {\n    let receipt = prepare_verification_receipt(workspace, input, verification)?;\n    ledger.record_receipt(receipt.clone())?;\n    Ok(receipt)\n}\n\nfn validate_tags(task_id: &str, tags: &[String]) -> Result<()> {\n    let mut seen = BTreeSet::new();\n    for tag in tags {\n        if tag.trim().is_empty() {\n            bail!(\"fleet task {task_id} tag cannot be empty\");\n        }\n        if !seen.insert(tag) {\n            bail!(\"fleet task {task_id} has duplicate tag {tag}\");\n        }\n    }\n    Ok(())\n}\n\nfn validate_workspace_requirements(task: &FleetTaskSpec) -> Result<()> {\n    let Some(workspace) = &task.workspace else {\n        return Ok(());\n    };\n    let env = workspace.environment.as_ref();\n    for name in env\n        .into_iter()\n        .flat_map(|env| env.required.iter().chain(env.allowlist.iter()))\n    {\n        if name.trim().is_empty() {\n            bail!(\n                \"fleet task {} environment variable name cannot be empty\",\n                task.id","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/fleet/task_spec.rs#L353-L389","documentation":"A fleet task spec was rejected during load because its `tags` array contains the same exact string twice. `validate_tags` (crates/tui/src/fleet/task_spec.rs) walks the tag list and inserts each tag into a BTreeSet; a second identical insert fails. Comparison is exact string equality (only the emptiness check trims), so \"api\" and \" api \" are distinct, but \"api\" twice is a duplicate.","triggerScenarios":"A TOML or JSON fleet task document (loaded via `load_task_spec_document`) with e.g. `tags = [\"backend\", \"backend\"]` on one task. Also specs generated programmatically that concatenate default tags with user tags without deduplicating.","commonSituations":"Copy-pasting tag lists between tasks; YAML/TOML anchors or merges that repeat a tag; generators that append a default tag (\"fleet\", \"audit\") on top of one the author already wrote.","solutions":["Find the task named in the message and delete the repeated tag so each appears once.","If the spec is generated, deduplicate with a set before serializing: tags.sort(); tags.dedup();","If you intended two similar tags, note the check is exact-match: differing whitespace/case counts as distinct, so normalize your tag source (trim, lowercase) at generation time instead."],"exampleFix":"# before (fleet task TOML)\n[[tasks]]\nid = \"audit-1\"\ntags = [\"backend\", \"audit\", \"backend\"]\n\n# after\n[[tasks]]\nid = \"audit-1\"\ntags = [\"backend\", \"audit\"]","handlingStrategy":"validation","validationCode":"fn check_tags(tags: &[String]) -> Result<(), String> {\n    let mut seen = std::collections::BTreeSet::new();\n    for tag in tags {\n        let t = tag.trim();\n        if t.is_empty() {\n            return Err(format!(\"empty tag: {tag:?}\"));\n        }\n        if !seen.insert(t) {\n            return Err(format!(\"duplicate tag: {tag:?}\"));\n        }\n    }\n    Ok(())\n}","typeGuard":"fn has_duplicate_tags(tags: &[String]) -> bool {\n    let mut seen = std::collections::BTreeSet::new();\n    tags.iter().any(|t| !seen.insert(t.trim()))\n}","tryCatchPattern":null,"preventionTips":["Deduplicate and trim tags at generation time: tags.sort(); tags.dedup();","Keep tag vocabularies in one shared constant instead of retyping them per task.","Run a spec lint step (validate_task_spec_document on the parsed doc) in CI before fleet runs."],"tags":["fleet","task-spec","validation","tags","rust"],"backgroundTag":"duplicate-config-entries","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}