magus v0.4.3 is out. See what's new
¶ View markdown source · ✎ Suggest an edit
2 min read

MGS1007: target dependency cycle

A target's dependencies form a cycle: following them leads back to the target itself, so it would have to finish before it could start. Magus detects this and errors instead of deadlocking.

[MGS1007] cross-project cycle: ../api target "build"
  see: .../MGS1007.md

Why

Targets declare what they depend on (ctx.needs(...), cross-project handles). Magus runs a target's dependencies before the target. If A depends on B and B depends on A (directly, or through a longer chain A -> B -> C -> A), there is no valid order: each is waiting on the other. Left unchecked that is a deadlock, so magus fails fast with this diagnostic naming the target the cycle closes on.

The check fires during cross-project dispatch: a (project, target) pair that is already on the current call stack when it is requested again is a cycle.

Resolution

Break the loop by removing one edge:

  • Find the back-edge. Follow the needs/cross-project dependencies from the named target until you return to it. One of those edges is the one to cut.
  • Invert or extract. If two targets genuinely need each other's output, factor the shared work into a third target both depend on, so the graph stays acyclic (A -> C, B -> C instead of A <-> B).
  • Cross-project cycles usually mean two projects each build-depend on the other. Decide which is the leaf and make the dependency one-directional.

Run magus describe graph (or open the Graph Explorer) to see the dependency edges and spot the cycle.

What this is not

  • Not a data race. A cycle is a structural dependency loop, not concurrent writes; those are the MGS4001-4004 race diagnostics.
  • Not caused by concurrency settings. Lowering concurrency does not resolve a cycle: the dependency graph itself has no valid order.

See also

  • targets: how targets declare dependencies.
  • magus describe graph: the dependency edges, to locate the cycle.
MGS1007magusfiletargetsneedsdependscyclecross-project
Last updated (353014be)
Earlier changes on this page (3)

Full history ↗ · Blame source ↗

Glossary

Project

A directory magus recognizes as a unit of work (it has a magusfile); the unit of caching, scheduling, and dependency tracking. Project in full.

Magusfile

The magusfile.buzz that declares a project's targets (as export funs) and binds its spells. Magusfile in full.

Target

A named operation (build, test, ...) you invoke with magus run <target>; it may compose a spell's tool-native operations and depend on other targets. Target in full.

Op

A single tool-native command a target composes (long form: operation); the middle of the work hierarchy (Spell to Op to Target). Op in full.

CI

An ordinary target you compose yourself with ctx.needs; magus does not hardcode its stages. It is the anchor magus affected ci keys off, and ci strips the rw charm. CI in full.

Concurrency

How many targets run at once. It is bounded by the pool's capacity and set with --concurrency, MAGUS_CONCURRENCY, or the concurrency config key. Concurrency in full.

Run

One target executing under one magus invocation, such as magus run test web or magus affected ci. A run keeps its captured output behind an output reference. Every magus run is a run whether or not any job asked for it; see Job for how the two relate. Run in full.

Conventions

This page uses none of the site's convention markers. The full set is on the conventions page.