Cargo "cyclic package dependency" in a Workspace in CI
Two crates depend on each other through their normal (build) dependencies, forming a cycle cargo cannot order. Cargo allows cycles only through dev-dependencies, so a build-dependency cycle is rejected.
What this error means
Resolution fails with error: cyclic package dependency: package A depends on itself and prints the chain (A -> B -> A). It appears after adding a dependency that closes a loop between workspace crates.
error: cyclic package dependency: package `a v0.1.0` depends on itself.
Cycle:
package `a v0.1.0 (.../crates/a)`
... which is depended on by `b v0.1.0 (.../crates/b)`
... which is depended on by `a v0.1.0`Common causes
Mutual build dependencies
Crate A lists B as a dependency and B lists A. Normal dependencies must form a DAG, so the cycle is rejected.
A dev-dependency promoted to a normal one
A cycle is allowed only via [dev-dependencies]. Moving such an edge into [dependencies] (or [build-dependencies]) closes a forbidden loop.
How to fix it
Break the cycle with a shared crate
Extract the common code into a third crate both depend on, removing the back-edge.
- Identify the two crates in the printed cycle.
- Move the shared types/logic into a new lower-level crate.
- Have both crates depend on the new crate instead of each other.
Keep the back-edge as a dev-dependency
If the reverse edge is only needed for tests, declare it under dev-dependencies, where cycles are permitted.
# crates/b/Cargo.toml
[dev-dependencies]
a = { path = "../a" } # cycle allowed for tests onlyHow to prevent it
- Keep workspace crate dependencies a DAG; extract shared crates to avoid loops.
- Confine unavoidable back-edges to
[dev-dependencies]. - Review the dependency direction before adding a cross-crate dep.