Files
hq/04-ISSUES/153-an-adopted-machines-data-cannot-be-placed-where-it-is/00-report.md
T
jschoubben b967ef7be3 Two records shared a number, twice, and every check passed
Two machines filing issues in the same hour both read main correctly and
both took "the next free number". main lags every open pull request —
seven that evening — so they collided twice. The second collision
reached main with records, cycle and index all reporting success.

cycle.py now refuses a tree where two issue folders share a leading
number, and names both. Proven by adding a duplicate and watching it
fail. The colliding records become 153 and 154, renumbered in the branch
that lands last, because renumbering a branch whose author is still
pushing only moves the race.

The check catches a collision; it does not prevent one. Taking a number
still means reading the open pull requests as well as main — issue 155
says so.
2026-09-29 23:38:48 +02:00

2.7 KiB

status, opened, located-in, fixed-by, amended-design
status opened located-in fixed-by amended-design
open 2026-09-29
mesh-controller internal/catalogue/dir_into.go (dirsFor
a stated path or <data root>/<module>/<id>, nothing else)
mesh-controller (accesses
the path is the manifest's literal)

153 — An adopted machine's data cannot be placed where it is

What was observed

Preparing ace's media modules (plex, sonarr, radarr, lidarr, bazarr, nzbget, qbittorrent, bookshelf) for migration. ace is adopted; its data is where the predecessor put it and must stay there:

  • the library and download spool: /storage/media/*, /storage/downloads — a separate ZFS pool, ~40 TB, the operator's shared data (ADR 0051);
  • plex's own state: /mnt/plex/{config,data,temp} — 133 GB on a second disk;
  • large configuration directories held in place: lidarr 46 GB, radarr 17 GB, sonarr 3.2 GB.

The catalogue's manifests name /services/media/* (as accesses) and /services/<m>/config (as owned directories), which is novox's layout, not ace's, and not a value a definition may carry.

What was decided, and what exists

ADR 0112 (accepted) says exactly what is needed:

Where it is on the machine is the assignment's. A node has a default layout, and an assignment may place a directory elsewhere: on a second disk, or where an adopted machine's data already is.

[ADR 0051]: an access keeps its shape and its semantics; its path moves from the definition to the assignment.

What the control plane implements (dirsFor): a directory is either a path the manifest states, or <data root>/<module>/<id> under the node's one data root. There is no per-assignment placement of one directory, and an access path is the manifest's literal — no setting reaches either.

Consequence

Every module whose data an adopted machine already holds somewhere other than the default layout can only be migrated by (a) writing the machine's path into the manifest — which 0112 forbids and which is wrong on the next machine — or (b) moving the data into the placed layout in a window. (b) is acceptable for a 40 MB configuration and impossible for a 40 TB library the operator has ruled must never be moved, copied or re-owned.

The same gap covers ownership: the predecessor runs ace's media stack as 1001:2000; a manifest's owner is one value for every machine.

What would be right

The two assignment halves 0112 decided: a setting that places a declared directory (by id) at a given path on this node, and a setting that says where an access's data is — both validated like endpoints (unknown ids refused), and an access placed by the assignment still never created, chowned or removed.