{"record":{"id":"4dfe50e632cf082a","repo":"vectordotdev/vector","slug":"duplicate-deprecation-fragments-for-what-in-and","errorCode":null,"errorMessage":"Duplicate deprecation fragments for `what`: '{}' (in {} and {})","messagePattern":"Duplicate deprecation fragments for `what`: '(.+?)' \\(in (.+?) and (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vdev/src/utils/deprecation.rs","lineNumber":136,"sourceCode":"        return Ok(Vec::new());\n    }\n    let mut paths: Vec<PathBuf> = fs::read_dir(dir)?\n        .filter_map(|e| e.ok().map(|e| e.path()))\n        .filter(|p| is_deprecation_fragment(p))\n        .collect();\n    paths.sort();\n    let entries: Vec<DeprecationEntry> = paths\n        .into_iter()\n        .map(|p| parse_deprecation_fragment(&p))\n        .collect::<Result<_>>()?;\n\n    // Reject duplicate `what` across pending fragments. A feature has one\n    // identity; two fragments with the same `what` would publish the same\n    // deprecation twice.\n    let mut seen: std::collections::HashMap<&str, &str> = std::collections::HashMap::new();\n    for e in &entries {\n        if let Some(prev) = seen.insert(e.what.as_str(), e.filename.as_str()) {\n            bail!(\n                \"Duplicate deprecation fragments for `what`: '{}' (in {} and {})\",\n                e.what,\n                prev,\n                e.filename\n            );\n        }\n    }\n    Ok(entries)\n}\n\nfn is_deprecation_fragment(path: &Path) -> bool {\n    let Some(name) = path.file_name().and_then(|n| n.to_str()) else {\n        return false;\n    };\n    if name == \"README.md\" {\n        return false;\n    }\n    if !std::path::Path::new(name)","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/vectordotdev/vector/blob/bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013/vdev/src/utils/deprecation.rs#L118-L154","documentation":"When scanning changelog.d for pending deprecation fragments, each `what` identifier must be unique — two fragments announcing the same deprecation would publish it twice. `read_deprecation_fragments` builds a map of `what` -> filename and bails if a duplicate is inserted. The error names both conflicting files.","triggerScenarios":"Running any consumer (append_enacted, rendered_json, sync_deprecations_cue, tests) that triggers `read_deprecation_fragments` when two fragment files in changelog.d declare the same `what` value in frontmatter.","commonSituations":"Copying an existing fragment and forgetting to change the `what` field; two PRs adding fragments for the same feature; rebasing leaving both an old and renamed fragment file behind.","solutions":["Find the two files named in the error and delete the redundant one","Change the `what` of one fragment if they genuinely describe different deprecations","Search changelog.d for the `what` string to confirm only one fragment remains","Re-run the deprecation sync/check after cleanup"],"exampleFix":"// before (two files)\n# changelog.d/remove_old_api.md  what: old_api\n# changelog.d/deprecate_old_api.md what: old_api\n// after\n# changelog.d/deprecate_old_api.md what: old_api   # keep only one","handlingStrategy":"validation","validationCode":"// before committing a fragment, ensure uniqueness of `what` across changelog.d\nlet whats: Vec<&str> = files.iter().map(|f| parse_what(f)).collect();\nassert_eq!(whats.len(), whats.iter().collect::<std::collections::HashSet<_>>().len());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Copy from a template but immediately change `what` to a unique identifier","grep changelog.d for the `what` string before adding a new fragment","Name fragment files after the `what` to make duplicates obvious in review"],"tags":["rust","deprecation","changelog","validation"],"backgroundTag":"file-already-exists","analyzedSha":"bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013","analyzedAt":"2026-09-16T02:53:35.741Z","contentChangedAt":"2026-09-16T02:53:35.741Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}