August 26, 2026 · v0.17.1 · containers · migrations · postmortem
The workspace moved after three processes were already confined to it
A migration that is correct on a host is a split brain in a container. The order of two startup steps is the whole bug.
Version 0.17.0 added a workspaces root. An install that never chose a workspace sat
outside the root that its own picker reports against, so the release moved
~/.nanoinfra/workspace to workspaces/default at gateway startup. On a
single-process host that is the right moment.
In a container it is too late, and the order says why:
entrypoint.shresolves the workspace.- It prepares the credential store and the job store under it.
- It starts the executor, the fetcher and the MCP host against it.
- And only now the gateway runs, and moves the directory.
The move leaves the agent on the new path and three confined helpers on a name that
no longer exists. Their Landlock rules, their secrets/ and their servers/jobs
all point at the old one. Every remote action then fails after the gate permits it,
and the Secrets page reads empty.
The fix is the order, not the code
The move happens in the entrypoint now, before the workspace is resolved. It calls the same function the gateway calls, because the guards are the point: only a pre-root default moves, never a symlink, never onto a destination that holds something, and a failed config rewrite moves the workspace back. The gateway then finds nothing left to do.
The shell fallback follows the code as well. A shell cannot read config.json, and
a default that lives in Python is exactly the pair that drifts apart, so a test pins
the two together.
What we verified
Not a fixture. We restored a copy of a real deployment’s volume and started the new image against it. The entrypoint moved the workspace. All three helpers came up on the new path. The credential store kept its owner and its mode, and the agent listed the credential its inventory references. The scheduled jobs and every transcript survived. A restart moved nothing and logged no traceback.