Repository navigation
macOS/OrbStack: sandbox.create fails with Connection refused after daemon LISTEN on LayerFS main (#500) #502
Description
Summary
On macOS + OrbStack, after moving from LayerFS v1.1.0 to main 35d36575 (includes #500), the normal-unmount Join wedge is gone, but 7 of 10 dsh-layerfs scripted scenarios now fail at sandbox.create with Connection refused.
The daemon has already printed:
LAYERFS_DAEMON_LISTEN 0.0.0.0:30421
Then the SDK's create attempt reports:
sandbox.create:Failed
sandbox create stopped at Connect: Io(Os { code: 111, kind: ConnectionRefused, message: "Connection refused" })
The failed container is removed (removed: true), so only the listener line remains in the captured log.
This appears separate from the Join/unmount issue in #466 / #426 / #460. #500 fixed the Join path in this matrix; it did not fix this Connect path.
Environment
| Host | macOS 26.7.1 (Darwin 25.6.0), arm64 |
| Docker Engine | OrbStack 29.8.2, API 1.56, kernel 7.2.12-orbstack-00394-gbecdd6130068, btrfs |
| Node | 24.22.0 |
| dsh | 0.2.1-rc.2, commit 687f282e8625c6b8d11ff58211a90524be2e4317 |
| LayerFS | 35d36575c1eb4d23d4b54534a7030d855db890e7 (main with #500) |
| Sealed bundle | build-linux-dcfb701326bc45c1aabc4f7461e0817d |
| Bundle manifest sha256 | 5dd14d96dc1be15d0bd7070269d6055dee75d53e8aeba7ab4da1c94e12092db9 |
| Runtime image | sha256:d0a62ee407258cc59e845634e2c8d39706a5d75e00e79dfed9877fe5807a5da5 |
| dsh-layerfs | b9bf3bc819b42007354f08c9444156188c4fbadb |
| Profile | default ~/.dsh/profiles/web |
For this test only, dsh-layerfs/layerfs.json was updated from fabefdf87a to 35d36575c1 so that #500 was exercised. No product source was changed. pnpm run check:layerfs reported the checkout at that pin; pnpm test and pnpm run test:scenarios passed; GET /layerfs/status reported missing: [] and worker: true.
Results
Matrix (10 scenarios, each invoked once; 3 at a time only when the queue allowed it):
| Scenario | Result | Time | Failing step |
|---|---|---|---|
| Conflicts | PASS | 0:02 | — |
| One Sandbox, two Workspaces | PASS | 0:21 | — |
| Checkpoints | PASS | 0:03 | — |
| Tour | FAIL | 0:01 | 4/14, sandbox.create |
| Parallel Branches | FAIL | 0:01 | 5/14, sandbox.create |
| Commit & merge | FAIL | 0:00 | 1/14, sandbox.create |
| 5 agents | FAIL | 0:09 | 42/197, sandbox.create |
| Shop | FAIL | 0:10 | 2/18, sandbox.create |
| Depot | FAIL | 0:18 | 2/98, sandbox.create |
| Crew | FAIL | 0:01 | 3/967, sandbox.create |
No scenario failed at workspace.unmount in this run. Conflicts and One Sandbox both passed, including their unmounts, which is consistent with #500 working.
Pattern
The failures are not tied to one scenario or to Store state:
Shop: the first sandbox was created and used; the second create (M1 test/publish) failed.Depot: the first sandbox was created and used; the second create (M1 build-domain) failed.5 agents: the initial create succeeded; a later create in thedeebranch failed.Tour,Commit & merge,Parallel Branches,Crew: failed at their first/early sandbox create.
A repeated create after a Sandbox has already been used is not required: Commit & merge failed on its first create.
Source path
The create path still waits for the listener log and then makes one TcpStream::connect_timeout:
engine/crates/layerfs-api/src/sandbox/create.rs:344-354- startup wait is
STARTUP = 30sinapi/binding/src/sandbox.rs - the listener marker is emitted after
TcpListener::bindinengine/crates/layerfs-daemon/src/application/cli.rs
Given the immediate ECONNREFUSED after the marker, this looks like the Docker-published endpoint not being ready when the first connect happens. The listener has bound inside the container, but the host-side port publication may not be ready yet.
Suggested direction
Could this be handled as a bounded readiness wait before the one create attempt?
- After the listener marker, retry opening the TCP connection on
ConnectionRefused(and possiblyTimedOut) untilstartup_wait, or wait until Docker reports the published endpoint. - This is a readiness probe, not a replay of
sandbox.create. - Alternatively, make the caller use the container address directly instead of the published port where the worker topology permits it.
I have not attempted a code fix. If this is a known OrbStack port-publication timing issue, documentation or a bounded connect wait would help.
Related
- dsh-layerfs 0.1.0 on OrbStack (kernel 7.0.14): 8/10 scripted scenarios stop at workspace.unmount (stage Join); Docker Desktop 4.22.0 cannot create Sandboxes (API 1.43 < 1.54) #466 — OrbStack 8/10 unmount Join issue; fix(daemon): integrate stalled unmount recovery with exact abort custody (#496) #500 now removes the Join wedge in this matrix.
- Workspace mounted while its Sandbox starts cannot be unmounted (
TeardownCustody { stage: Join }) and stays wedged #426 — early mount / Join custody; closed by fix(daemon): end a normal unmount stalled at Join with one forced unmount (#426, #460) #481. - FUSE readers remain blocked after successful unmount: independent reproducer and Linux comparison (related to #426) #460 — FUSE readers blocked after successful unmount; still open.
- I did not find an existing issue with this
sandbox.create+ConnectionRefusedsignature.
No product code was changed in producing this report. The scenario projects and trace files were retained for inspection.
Activity