Description
nemoclaw {sandbox} stop returns success but does not tear down the host-side dashboard SSH port-forward it created. After stop, a nemoclaw-spawned ssh ... -L 127.0.0.1:18789:127.0.0.1:18789 sandbox keeps LISTENing on the dashboard port. As a result nemoclaw {sandbox} status classifies the cleanly stopped sandbox via sandbox_dashboard_port_conflict ("the dashboard port is held by a foreign listener" — actually nemoclaw's own leftover forward), and nemoclaw {sandbox} start / nemoclaw {sandbox} recover intermittently fail their gateway-readiness probe (contending for the still-held port / probing before the restarted container is healthy).
Related but distinct from #7222: that issue covers the downstream recovery hint (status recommends rebuild --yes, which aborts on the pre-rebuild backup gate; start is the real recovery). This report is the upstream cause on stop (the dashboard port-forward is left running) plus the intermittent start/recover gateway-probe failures — neither of which #7222 exercises (it crashes the container with docker kill, never runs nemoclaw stop).
Platform scope: Reproduced on DGX Spark (GB10, aarch64) only; other platforms not tested. Root cause (host-side port-forward not torn down on stop) appears platform-independent.
Regression: Unknown — earlier versions not tested.
Environment
Device: DGX Spark (GB10, aarch64)
OS: Ubuntu 24.04
Architecture: aarch64
Node.js: v22.22.1
npm: 10.9.4
Docker: 28.3.3
OpenShell CLI: 0.0.85
NemoClaw: v0.0.88
OpenClaw: 2026.6.10
Steps to Reproduce
- Onboard an OpenClaw sandbox (e.g.
{sandbox}) on ollama-local; confirm Phase: Ready and note the dashboard port (e.g. 18789).
- On the host, list listeners on the dashboard port; a nemoclaw-spawned forward holds it:
ss -ltnp | grep 18789
# -> LISTEN 127.0.0.1:18789 ... users:(("ssh",pid={pid}))
# that ssh is: ssh ... -o ExitOnForwardFailure=yes -L 127.0.0.1:18789:127.0.0.1:18789 sandbox
- Stop the sandbox:
nemoclaw {sandbox} stop # exits 0; container goes to Exited (137)
- Re-check the dashboard port on the host:
ss -ltnp | grep 18789
# -> the SAME ssh -L 127.0.0.1:18789 forward is STILL listening (orphaned; stop did not tear it down)
- Check status:
nemoclaw {sandbox} status (see Actual Result).
- Repeat a few times:
nemoclaw {sandbox} start
nemoclaw {sandbox} recover
# observe intermittent gateway-probe failures (EXIT 1) that leave the container Exited, vs other runs that succeed
Expected Result
nemoclaw {sandbox} stop tears down the host-side dashboard port-forward it created; no listener remains on the dashboard port after stop.
nemoclaw {sandbox} status on a cleanly stopped sandbox does not report a sandbox_dashboard_port_conflict caused by nemoclaw's own leftover forward.
nemoclaw {sandbox} start / recover deterministically restart the container and wait for it to become healthy before reporting success or failure — no intermittent false failure while the container is still coming up.
Actual Result
After nemoclaw {sandbox} stop (exit 0; container Exited 137), the dashboard forward is still alive:
$ ss -ltnp | grep 18789
LISTEN 0 128 127.0.0.1:18789 0.0.0.0:* users:(("ssh",pid={pid},fd=3))
$ nemoclaw {sandbox} status # EXIT 1
Failure layer: sandbox_dashboard_port_conflict — sandbox container is stopped and the dashboard port is held by a foreign listener.
Phase: Error
start / recover are flaky across repeats:
$ nemoclaw {sandbox} start # sometimes EXIT 1
Probe failed: OpenClaw gateway is not running in '{sandbox}' and automatic recovery failed.
$ nemoclaw {sandbox} recover # sometimes EXIT 1
Probe failed: could not inspect the OpenClaw gateway inside sandbox '{sandbox}'.
# other runs: EXIT 0 "recovered OpenClaw gateway", container Up healthy in ~30-50s
Logs
# openshell reports the stopped sandbox as Provisioning (not Stopped):
$ openshell sandbox list
NAME CREATED PHASE
{sandbox} 2026-07-20 ... Provisioning
# docker: the container was SIGKILLed by stop
{container} :: Exited (137)
# the orphaned host-side forward (sandbox-id and token scrubbed):
ssh -o ProxyCommand='.../openshell ssh-proxy --gateway https://127.0.0.1:8080 --sandbox-id {sandbox-id} --token {token} --gateway-name nemoclaw ...' -N -o ExitOnForwardFailure=yes -L 127.0.0.1:18789:127.0.0.1:18789 sandbox
# Recovery that reliably works: `nemoclaw {sandbox} start` until the container is Up/healthy
# (openshell PHASE=Ready), after which status is EXIT 0 Ready and agent inference works — the
# sandbox is never actually corrupted. Still reproduces on v0.0.88 / OpenShell 0.0.85.
Description
nemoclaw {sandbox} stopreturns success but does not tear down the host-side dashboard SSH port-forward it created. After stop, a nemoclaw-spawnedssh ... -L 127.0.0.1:18789:127.0.0.1:18789 sandboxkeeps LISTENing on the dashboard port. As a resultnemoclaw {sandbox} statusclassifies the cleanly stopped sandbox viasandbox_dashboard_port_conflict("the dashboard port is held by a foreign listener" — actually nemoclaw's own leftover forward), andnemoclaw {sandbox} start/nemoclaw {sandbox} recoverintermittently fail their gateway-readiness probe (contending for the still-held port / probing before the restarted container is healthy).Related but distinct from #7222: that issue covers the downstream recovery hint (status recommends
rebuild --yes, which aborts on the pre-rebuild backup gate;startis the real recovery). This report is the upstream cause onstop(the dashboard port-forward is left running) plus the intermittentstart/recovergateway-probe failures — neither of which #7222 exercises (it crashes the container withdocker kill, never runsnemoclaw stop).Platform scope: Reproduced on DGX Spark (GB10, aarch64) only; other platforms not tested. Root cause (host-side port-forward not torn down on stop) appears platform-independent.
Regression: Unknown — earlier versions not tested.
Environment
Steps to Reproduce
{sandbox}) on ollama-local; confirmPhase: Readyand note the dashboard port (e.g. 18789).nemoclaw {sandbox} stop # exits 0; container goes to Exited (137)nemoclaw {sandbox} status(see Actual Result).nemoclaw {sandbox} start nemoclaw {sandbox} recover # observe intermittent gateway-probe failures (EXIT 1) that leave the container Exited, vs other runs that succeedExpected Result
nemoclaw {sandbox} stoptears down the host-side dashboard port-forward it created; no listener remains on the dashboard port after stop.nemoclaw {sandbox} statuson a cleanly stopped sandbox does not report asandbox_dashboard_port_conflictcaused by nemoclaw's own leftover forward.nemoclaw {sandbox} start/recoverdeterministically restart the container and wait for it to become healthy before reporting success or failure — no intermittent false failure while the container is still coming up.Actual Result
After
nemoclaw {sandbox} stop(exit 0; container Exited 137), the dashboard forward is still alive:start/recoverare flaky across repeats:Logs