Orphaned registry rows are never reconciled against live containers #439
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The defect
Registry rows outlive their containers, and nothing ever cleans them up.
A row only leaves the registry two ways: an explicit
teardown_bottle(the launcher's cleanup callback), or the same-IP supersede sweep inregister(). Neither runs if the launching CLI dies hard — SIGKILL, a closed terminal, a host sleep. There is no reconciliation of registry rows against live containers anywhere in the codebase, so a row left behind staysactiveforever.Verified on the host:
bot-bottle-claude-agent-1was registeredactiveat192.168.128.6with no container running (not even stopped) and no/gitnamespace. A pure orphan.Why it matters
RegistryStore.by_source_ipfail-closes whenlen(rows) != 1— zero rows and ambiguous rows both resolve to "no policy", and a bottle with no policy is denied every host. Source IPs are recycled by the backend's DHCP, so an orphan sitting on an address is a live collision hazard for whatever bottle lands there next.Being precise about status: the accumulation is observed and the fail-closed-on-ambiguity behaviour is plain in the code, but I never caught an orphan actually colliding with a new bottle. This is a reachable hazard, not a witnessed failure. It is worth fixing on its own terms — an
activerow for a container that no longer exists is wrong regardless of whether it has bitten yet — but it should not be credited with any outage so far.Fix
PR #440:
RegistryStore.reap_absent/Orchestrator.reconcile+POST /reconcile, called from the macOS launch path before registering, so each launch self-heals.Note on deployment
The control-plane source is bind-mounted with a
BOT_BOTTLE_SOURCE_HASHstaleness check, so the first launch after this lands recreates the shared infra container — which strands any running bottle, see #443.Resolved from the original writeup
The "first 403 exactly 30.0 minutes in" mystery is explained: the Codex session never made a successful call at all. Its first network activity was a background
list_modelsrefresh half an hour in, and that was denied like everything else. The cause was #441 throughout.Related
*_PROXYenv drops the identity token. The actual cause of the Codex outage.Orphaned registry rows brick the next bottle at a recycled source IPto Orphaned registry rows are never reconciled against live containers