{"record":{"id":"427c09b08a3afbf2","repo":"astrid-runtime/astrid","slug":"duplicate-corpus-label","errorCode":null,"errorMessage":"duplicate corpus label {:?}","messagePattern":"duplicate corpus label (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-chunker-evidence/src/main.rs","lineNumber":127,"sourceCode":"    for (name, repository, relative_path) in &options.git_history_specs {\n        corpora.push(Corpus::version_chain_from_git(\n            name.clone(),\n            repository,\n            relative_path,\n        )?);\n    }\n    if corpora.is_empty() {\n        bail!(\"no corpus selected; omit --no-synthetic or pass a corpus or version-chain option\");\n    }\n    ensure_unique_corpus_labels(&corpora)?;\n    Ok(corpora)\n}\n\nfn ensure_unique_corpus_labels(corpora: &[Corpus]) -> Result<()> {\n    let mut labels = HashSet::with_capacity(corpora.len());\n    for corpus in corpora {\n        if !labels.insert(corpus.name()) {\n            bail!(\"duplicate corpus label {:?}\", corpus.name());\n        }\n    }\n    Ok(())\n}\n\nfn write_report(output: Option<&PathBuf>, report: &EvidenceReport) -> Result<()> {\n    let mut encoded = serde_json::to_string(report)?;\n    encoded.push('\\n');\n    if let Some(path) = output {\n        fs::write(path, encoded)\n            .with_context(|| format!(\"write evidence report {}\", path.display()))?;\n    } else {\n        println!(\"{encoded}\");\n    }\n    Ok(())\n}\n\nfn parse_options() -> Result<Options> {","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-chunker-evidence/src/main.rs#L109-L145","documentation":"`ensure_unique_corpus_labels` inserts each corpus name into a HashSet and bails on the first duplicate. Duplicate labels would collide in reports (and potentially in output filenames), so the library refuses ambiguous configurations.","triggerScenarios":"Passing the same `NAME=` twice (e.g. two `--git-history samples=...` specs, or a `--corpus` whose derived label equals another corpus's label).","commonSituations":"Copy-pasting a CLI line and forgetting to change the label, two directories normalizing to the same slug after label sanitization, or scripting loops that reuse a fixed name.","solutions":["Give each corpus a distinct label in its spec (`--git-history samples2=...`)","Rename one corpus directory or pass an explicit unique name if the tool derives labels from paths","Before running, list your corpus labels and dedupe them in your script"],"exampleFix":"// before\nbin --git-history samples=repo::a.bin --git-history samples=repo::b.bin\n// after\nbin --git-history samples-a=repo::a.bin --git-history samples-b=repo::b.bin","handlingStrategy":"validation","validationCode":"fn labels_unique(specs: &[String]) -> bool {\n    let mut seen = std::collections::HashSet::new();\n    specs.iter().all(|s| seen.insert(s.split('=').next().unwrap_or(\"\").to_string()))\n}\nassert!(labels_unique(&git_history_args));","typeGuard":null,"tryCatchPattern":"match run_cli(args) {\n    Err(e) if e.to_string().starts_with(\"duplicate corpus label\") => {\n        eprintln!(\"deduping corpus labels and rerunning\");\n        run_cli(&dedupe_labels(&args))\n    }\n    other => other,\n}","preventionTips":["Namespace labels in generated scripts (e.g. include an index: samples-1, samples-2)","Check for duplicates after label sanitization, not just before","Keep one source of truth for corpus definitions instead of hand-written flag lists"],"tags":["rust","cli","duplicate","configuration"],"backgroundTag":"duplicate-identifier","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}