Skip to content

[DGX Spark][CLI&UX] stop leaves the dashboard port-forward alive; status flags sandbox_dashboard_port_conflict and start/recover intermittently fail #7227

Description

@hulynn

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

  1. Onboard an OpenClaw sandbox (e.g. {sandbox}) on ollama-local; confirm Phase: Ready and note the dashboard port (e.g. 18789).
  2. 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
  3. Stop the sandbox:
    nemoclaw {sandbox} stop            # exits 0; container goes to Exited (137)
  4. 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)
  5. Check status: nemoclaw {sandbox} status (see Actual Result).
  6. 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.

Metadata

Metadata

Assignees

Labels

NV QABugs found by the NVIDIA QA TeamUATIssues flagged for User Acceptance Testing.VDRLinked to VDR finding

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions