The derived-value record is renumbered a second time: the key-value-buckets record took 0201 while this waited to merge, as the bundles record took 0188 before it. Both times free when chosen, taken by the time it landed. cycle.py caught it; three repositories cite this record, so the number matters. 225 — a provisioner has not been able to read its grant secrets since 01:30, when a module's own code left its container and the files stayed root's. Four thousand refusals, each worded as patience, and two consumers unserved. Not from ADR 0202 or 0189, which landed hours later; dates in the report. 226 — the store's sweep stops at the first reference recorded with an address and collects nothing. A guard that cannot tell 'I will not ask about this' from 'it would not answer' stops the wrong amount of work. 227 — the photo app's admin client asks for the port the proxy holds. A module pinned months behind carries everything its branch gained, the first time anything makes it move.
2.8 KiB
status, opened, located-in, fixed-by, amended-design
| status | opened | located-in | fixed-by | amended-design | ||
|---|---|---|---|---|---|---|
| open | 2026-10-04 |
|
226 — The store's sweep stops at the first reference recorded with an address, so it collects nothing at all
What was observed
The first live run of ADR 0189's sweep, 2026-10-04, printed on every build:
the artifact store kept 127.0.0.1:5100/mesh-tools/build@sha256:0de48cd3…, so nothing more was
asked of it: 127.0.0.1:5100/mesh-tools/build@sha256:0de48cd3… is not a reference into the
mesh's artifact store
1681 more to collect; the next build asks again
Nothing is collected, and nothing ever will be. The store holds 1681 artifacts the mesh no longer keeps and the feature that exists to remove them is inert.
Why
Two correct decisions meeting badly.
A reference recorded before references were kept without an address is
127.0.0.1:5100/<path>@sha256:… rather than artifact-store://<path>@sha256:…
(04-ISSUES/102).
LetGo rightly refuses to compose a delete for a reference whose shape it does not recognise —
that refusal is what keeps the sweep from reaching something that is not the mesh's.
The sweep stops at the first refusal, because "a store that refuses one refuses all of them" — deletion disabled, the store down, the network gone — and pushing through would mean a hundred identical failures in front of whoever was building something. That reasoning is right for the store refusing. It is wrong for this record being unreadable.
So one old record, early in the oldest-first order, halts the whole sweep for ever.
Why it matters beyond this instance
A guard that cannot tell "I will not ask about this" from "it would not answer" stops the wrong amount of work. The two deserve opposite responses: skip one, abandon the other. Collapsing them into "an error" is how a bounded, cautious loop becomes a loop that does nothing — and it reports the right number while doing it, which is what made it look healthy.
What a fix has to settle
- A reference the sweep cannot address is skipped, and the sweep goes on — it is a fact about that record, not about the store.
Recorded()already normalises the old form to the kept one, and is what the rest of the mesh uses for exactly these references. The sweep should normalise before asking rather than refuse.- Only a refusal by the store ends a sweep.
- How it is checked: a sweep over records holding one address-recorded reference and one kept one collects the second; a sweep against a store that refuses stops at the first.