{"record":{"id":"3992c1960c9cf898","repo":"jdx/mise","slug":"workspace-project-id-cannot-both-add-and-remov","errorCode":null,"errorMessage":"workspace project {id:?} cannot both add and remove dependency {dependency:?}","messagePattern":"workspace project (.+?) cannot both add and remove dependency (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/task/workspace.rs","lineNumber":1166,"sourceCode":"    }\n}\n\nfn validate_override(id: &ProjectId, config: &WorkspaceProjectOverride) -> Result<()> {\n    if config.remove\n        && (config.root.is_some()\n            || config.metadata.is_some()\n            || config.depends.is_some()\n            || !config.depends_add.is_empty()\n            || !config.depends_remove.is_empty())\n    {\n        bail!(\"removed workspace project {id:?} cannot define other overrides\");\n    }\n    if let Some(dependency) = config\n        .depends_add\n        .intersection(&config.depends_remove)\n        .next()\n    {\n        bail!(\"workspace project {id:?} cannot both add and remove dependency {dependency:?}\");\n    }\n    Ok(())\n}\n\nfn parse_dependency_ids(\n    project_id: &ProjectId,\n    field: &str,\n    dependencies: &BTreeSet<String>,\n) -> Result<BTreeSet<ProjectId>> {\n    dependencies\n        .iter()\n        .map(|dependency| {\n            dependency.parse::<ProjectId>().map_err(|err| {\n                eyre::eyre!(\n                    \"workspace project {project_id:?} has invalid {field} entry {dependency:?}: {err}\"\n                )\n            })\n        })","sourceCodeStart":1148,"sourceCodeEnd":1184,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/task/workspace.rs#L1148-L1184","documentation":"A [monorepo.projects.\"<id>\"] override cannot list the same dependency in both depends_add and depends_remove. validate_override() checks the intersection of the two sets and rejects any overlap, because add+remove of the same edge is contradictory (order of application is depends replacement, then remove, then add, so the intent is ambiguous).","triggerScenarios":"An override entry where depends_add and depends_remove share an element, e.g. depends_add = [\"cargo:shared\"], depends_remove = [\"cargo:shared\"]; usually a typo or an attempt to 'move' an edge that ends up listed on both sides.","commonSituations":"Editing a long depends_add/depends_remove list during refactor; merge conflict resolution duplicating an entry into both keys; attempting to toggle an edge via two config layers.","solutions":["Decide the final state: keep the edge only in depends_add, or only in depends_remove","To replace the whole dependency set, use depends = [...] alone (full replacement) instead of add+remove pairs","After merge conflicts, grep the entry for the duplicated ID in both lists"],"exampleFix":"# before (mise.toml)\n[monorepo.projects.\"cargo:app\"]\ndepends_add = [\"cargo:shared\", \"cargo:util\"]\ndepends_remove = [\"cargo:shared\"]\n\n# after\n[monorepo.projects.\"cargo:app\"]\ndepends_add = [\"cargo:util\"]","handlingStrategy":"validation","validationCode":"for (raw_id, cfg) in &overrides {\n    if let Some(dup) = cfg.depends_add.intersection(&cfg.depends_remove).next() {\n        return Err(eyre::eyre!(\"entry {raw_id}: {dup} appears in both depends_add and depends_remove\"));\n    }\n}","typeGuard":"fn add_remove_are_disjoint(cfg: &WorkspaceProjectOverride) -> bool {\n    cfg.depends_add.is_disjoint(&cfg.depends_remove)\n}","tryCatchPattern":null,"preventionTips":["Prefer depends = [...] full replacement when rewriting edges — it cannot conflict with itself","Lint [monorepo.projects] entries in CI (tomlq/jq check for intersection) before commit","After merge conflicts, deduplicate dependency IDs across both lists"],"tags":["rust","mise","workspace","config-validation","toml"],"backgroundTag":"conflicting-config-values","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}