jdx/mise · error

workspace project {id:?} cannot both add and remove dependen

Error message

workspace project {id:?} cannot both add and remove dependency {dependency:?}

What it means

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).

Source

Thrown at src/task/workspace.rs:1166

    }
}

fn validate_override(id: &ProjectId, config: &WorkspaceProjectOverride) -> Result<()> {
    if config.remove
        && (config.root.is_some()
            || config.metadata.is_some()
            || config.depends.is_some()
            || !config.depends_add.is_empty()
            || !config.depends_remove.is_empty())
    {
        bail!("removed workspace project {id:?} cannot define other overrides");
    }
    if let Some(dependency) = config
        .depends_add
        .intersection(&config.depends_remove)
        .next()
    {
        bail!("workspace project {id:?} cannot both add and remove dependency {dependency:?}");
    }
    Ok(())
}

fn parse_dependency_ids(
    project_id: &ProjectId,
    field: &str,
    dependencies: &BTreeSet<String>,
) -> Result<BTreeSet<ProjectId>> {
    dependencies
        .iter()
        .map(|dependency| {
            dependency.parse::<ProjectId>().map_err(|err| {
                eyre::eyre!(
                    "workspace project {project_id:?} has invalid {field} entry {dependency:?}: {err}"
                )
            })
        })

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Decide the final state: keep the edge only in depends_add, or only in depends_remove
  2. To replace the whole dependency set, use depends = [...] alone (full replacement) instead of add+remove pairs
  3. After merge conflicts, grep the entry for the duplicated ID in both lists

Example fix

# before (mise.toml)
[monorepo.projects."cargo:app"]
depends_add = ["cargo:shared", "cargo:util"]
depends_remove = ["cargo:shared"]

# after
[monorepo.projects."cargo:app"]
depends_add = ["cargo:util"]
Defensive patterns

Strategy: validation

Validate before calling

for (raw_id, cfg) in &overrides {
    if let Some(dup) = cfg.depends_add.intersection(&cfg.depends_remove).next() {
        return Err(eyre::eyre!("entry {raw_id}: {dup} appears in both depends_add and depends_remove"));
    }
}

Type guard

fn add_remove_are_disjoint(cfg: &WorkspaceProjectOverride) -> bool {
    cfg.depends_add.is_disjoint(&cfg.depends_remove)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/3992c1960c9cf898. Report an issue: GitHub.