## TL;DR

Break the circular dependency by restructuring so data flows one way: merge the cells or move shared state into a parent cell.
Marimo builds a directed graph of cell dependencies; a cycle means no valid execution order exists, so it stops instead of looping forever.
Put the shared variable definition in one upstream cell and have both cells read from it.

```text
marimo notebook crashed: reactive cycle detected between two cells
```

## Use this when

- marimo reports a reactive cycle detected naming two cells
- Editing one cell triggers the other in an infinite ping-pong
- The notebook ran as a plain script but fails as a reactive marimo app

## Not for this skill when

- marimo fails to start at all - that is item 116
- Export to ipynb loses reactivity - that is an export limitation
- A single cell raises an exception - that is a code problem

## Steps

1. Read the cycle report: marimo names the cells and variables in the loop.
   Expected: two cells where A defines x used by B and B defines y used by A.

2. Decide the true data flow: which variable is genuinely upstream.
   Expected: a clear one-way ordering once you name the producer and the consumer.

3. Restructure: move the shared definition into a single upstream cell, or merge the two cells into one that computes both values in order.
   Expected: no cell both reads and writes the cycled variables.

4. Re-run the notebook.
   Expected: marimo builds the graph without a cycle error and cells execute topologically.

5. Add a comment at the merged cell explaining the ordering constraint so future edits do not reintroduce the cycle.
   Expected: the constraint is documented in the code.

## Tool compatibility

marimo 0.9+ / 0.10+, Python 3.9+

## Variant phrasings

### marimo reactive cycle detected between cells

Same fix applies: see the Steps section above.

### marimo circular dependency cells

Same fix applies: see the Steps section above.

### marimo cycle error how to fix

Same fix applies: see the Steps section above.

## Why it happens

Marimo's reactivity is a static dataflow graph: each cell declares variables, and marimo topologically sorts cells so definitions precede uses. A cycle (A needs B's output and B needs A's output) has no topological order, so marimo refuses to run rather than pick an arbitrary order and produce silently wrong results. Plain notebooks tolerate cycles because cells run in manual order, which is exactly the footgun marimo eliminates. The fix is always structural: the shared state must live in one place with a single direction of flow.

## Edge cases / pitfalls

- Mutating a shared mutable object across cells can hide a logical cycle the graph cannot see; prefer immutable flow.
- Cells that only read a variable both ways are fine; the cycle needs a definition on each side.
- Refactoring into functions does not fix a true data cycle; the dependency structure must change.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_iEs1x76VIJRtQldUzEK6mQ
