## TL;DR

Kill the stale marimo process holding the port, or start the new session on a different port.
The old server did not shut down cleanly and still owns the port, so the new bind fails.
Find the process with the port, terminate it, then start marimo fresh.

```text
marimo failed to start: port already in use by a stale session
```

## Use this when

- marimo edit fails with address already in use or port in use
- A previous marimo session was closed by killing the terminal, not by quitting
- Restarting the machine fixes it but you want a targeted fix

## Not for this skill when

- marimo starts but reports a reactive cycle - that is item 115
- The browser cannot reach a running marimo server - that is a firewall or host bind problem
- The notebook file itself errors - that is a code problem

## Steps

1. Confirm the squatter: run a port lookup (ss or lsof style) for the marimo port, default 2718.
   Expected: a python process listed as listening on that port.

2. Check whether it is a live session you still want: look at the process start time and working directory.
   Expected: a stale process from an earlier session, not current work.

3. Terminate it gracefully, then forcefully if needed.
   Expected: the port lookup comes back empty.

4. Start marimo again: marimo edit notebook.py.
   Expected: the server binds and prints its URL.

5. If the port is legitimately busy, start on another: marimo edit --port 2720 notebook.py.
   Expected: the server binds to the new port cleanly.

## Tool compatibility

marimo 0.9+ / 0.10+, Python 3.9+

## Variant phrasings

### marimo port already in use

Same fix applies: see the Steps section above.

### marimo address already in use stale session

Same fix applies: see the Steps section above.

### marimo failed to bind port

Same fix applies: see the Steps section above.

## Why it happens

Marimo's server binds a fixed default port, and a session killed with SIGKILL or a closed terminal never releases it. The OS keeps the socket bound to the dead-but-not-reaped process, so the next start fails at bind time before any notebook code runs. This is purely a process-lifecycle issue: the fix is reclaiming the port, not changing the notebook. Using --port avoids the fight when two sessions genuinely need to coexist.

## Edge cases / pitfalls

- Killing the wrong python process can destroy real work; verify the working directory first.
- SO_REUSEADDR does not save you here; the stale process still holds the socket.
- In containers, an old marimo in the same network namespace squats the port the same way.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_pbnyo-LXWXjKJ4qCGyUMHQ
