fix: resolve GPU sandbox creation failures on DGX machines - #238
Conversation
Three bugs caused onboarding to silently fail on DGX when GPU was detected: 1. Pipe masked sandbox creation exit code: `openshell sandbox create ... | awk` exits with awk's status (0), not openshell's, so GPU errors were ignored and NemoClaw reported success while no sandbox existed — causing "sandbox not found" in Step 7. Fixed with `set -o pipefail`. 2. GPU device plugin race on DGX: the k3s GPU device plugin needs extra time to register GPUs with the Kubernetes scheduler after the gateway HTTP endpoint becomes healthy. The 5-second DNS sleep was not enough. Added a polling loop (up to 2 minutes) for GPU allocatability before sandbox creation. 3. Stale port 18789 forward from a previous onboard blocked the new sandbox's dashboard port. Added explicit `openshell forward stop 18789` cleanup before the new forward. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The official NVIDIA DGX Spark playbooks do not use --gpu on openshell gateway start or sandbox create. On Spark, inference is routed through a host-side provider (Ollama, vLLM, or cloud API) via openshell's inference routing layer — the sandbox does not need direct GPU access. Passing --gpu causes FailedPrecondition errors because the gateway's k3s GPU device plugin cannot allocate GPUs on Spark, which cascades into sandbox creation failures and broken policy application. Removes the GPU allocatability poll loop (no longer needed) while preserving the pipefail and stale port forward fixes from the parent commit. Refs: #239 See: https://build.nvidia.com/spark/nemoclaw/instructions
ericksoa
left a comment
There was a problem hiding this comment.
Pushed a follow-up commit (21c98f8) on top of yours.
Your pipefail and stale port forward fixes are solid and I kept them as-is. The additional commit removes --gpu from gateway start and sandbox create entirely, and drops the GPU allocatability poll loop.
Why: The official NVIDIA DGX Spark playbook does not use --gpu on openshell gateway start or openshell sandbox create. On Spark, inference is routed through a host-side provider (Ollama/vLLM/cloud API) via openshell provider create + openshell inference set — the sandbox never needs direct GPU access. The playbook's troubleshooting table even says "No GPU detected → Expected on DGX Spark; proceeds normally."
GPU resources will never become allocatable on Spark because that's not how the architecture works, so the poll loop would always time out (2 min wait for nothing). With your pipefail fix, that timeout would then surface as a hard failure — correct behavior given the premise, but the premise itself is wrong.
Filed #239 to track this.
|
e2e complete along with testing race conditions and stale scenarios on main and with fixes. |
* fix: resolve GPU sandbox creation failures on DGX machines (NVIDIA#235) Three bugs caused onboarding to silently fail on DGX when GPU was detected: 1. Pipe masked sandbox creation exit code: `openshell sandbox create ... | awk` exits with awk's status (0), not openshell's, so GPU errors were ignored and NemoClaw reported success while no sandbox existed — causing "sandbox not found" in Step 7. Fixed with `set -o pipefail`. 2. GPU device plugin race on DGX: the k3s GPU device plugin needs extra time to register GPUs with the Kubernetes scheduler after the gateway HTTP endpoint becomes healthy. The 5-second DNS sleep was not enough. Added a polling loop (up to 2 minutes) for GPU allocatability before sandbox creation. 3. Stale port 18789 forward from a previous onboard blocked the new sandbox's dashboard port. Added explicit `openshell forward stop 18789` cleanup before the new forward. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: stop passing --gpu to gateway and sandbox on DGX Spark The official NVIDIA DGX Spark playbooks do not use --gpu on openshell gateway start or sandbox create. On Spark, inference is routed through a host-side provider (Ollama, vLLM, or cloud API) via openshell's inference routing layer — the sandbox does not need direct GPU access. Passing --gpu causes FailedPrecondition errors because the gateway's k3s GPU device plugin cannot allocate GPUs on Spark, which cascades into sandbox creation failures and broken policy application. Removes the GPU allocatability poll loop (no longer needed) while preserving the pipefail and stale port forward fixes from the parent commit. Refs: NVIDIA#239 See: https://build.nvidia.com/spark/nemoclaw/instructions --------- Co-authored-by: NemoClaw Dev <dev@nemoclaw.local> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Aaron Erickson <aerickson@nvidia.com>
* fix: resolve GPU sandbox creation failures on DGX machines (NVIDIA#235) Three bugs caused onboarding to silently fail on DGX when GPU was detected: 1. Pipe masked sandbox creation exit code: `openshell sandbox create ... | awk` exits with awk's status (0), not openshell's, so GPU errors were ignored and NemoClaw reported success while no sandbox existed — causing "sandbox not found" in Step 7. Fixed with `set -o pipefail`. 2. GPU device plugin race on DGX: the k3s GPU device plugin needs extra time to register GPUs with the Kubernetes scheduler after the gateway HTTP endpoint becomes healthy. The 5-second DNS sleep was not enough. Added a polling loop (up to 2 minutes) for GPU allocatability before sandbox creation. 3. Stale port 18789 forward from a previous onboard blocked the new sandbox's dashboard port. Added explicit `openshell forward stop 18789` cleanup before the new forward. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: stop passing --gpu to gateway and sandbox on DGX Spark The official NVIDIA DGX Spark playbooks do not use --gpu on openshell gateway start or sandbox create. On Spark, inference is routed through a host-side provider (Ollama, vLLM, or cloud API) via openshell's inference routing layer — the sandbox does not need direct GPU access. Passing --gpu causes FailedPrecondition errors because the gateway's k3s GPU device plugin cannot allocate GPUs on Spark, which cascades into sandbox creation failures and broken policy application. Removes the GPU allocatability poll loop (no longer needed) while preserving the pipefail and stale port forward fixes from the parent commit. Refs: NVIDIA#239 See: https://build.nvidia.com/spark/nemoclaw/instructions --------- Co-authored-by: NemoClaw Dev <dev@nemoclaw.local> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Aaron Erickson <aerickson@nvidia.com>
Problem
Running
nemoclaw onboardon a DGX machine (or any host with an NVIDIA GPU wherenimCapable = true) fails silently in Step 3, then crashes in Step 7 with:The user sees "✓ Sandbox created" but the sandbox was never actually created in openshell, leaving them with a broken, half-configured install.
Root Cause Analysis
Three bugs conspire to produce this failure:
Bug 1 — Pipe masks sandbox creation exit code (primary cause of "sandbox not found")
File:
bin/lib/onboard.js:204Bash pipelines return the last command's exit code —
awk's, notopenshell's. Whenopenshell sandbox create --gpufails,awkprocesses the error output and exits 0.run()checksresult.status !== 0and sees nothing wrong, so execution continues. NemoClaw registers the sandbox in its local registry and prints✓ Sandbox 'X' createdeven though openshell never created it. Step 7 then callsopenshell policy set ... <sandbox-name>on a sandbox that doesn't exist → "sandbox not found".Bug 2 — GPU device plugin not ready on DGX (root trigger)
File:
bin/lib/onboard.js:109–145The gateway health check only polls
openshell statusuntil it reports "Connected" (HTTP endpoint up), then sleeps 5 seconds for DNS. On DGX machines running k3s-inside-Docker, the NVIDIA GPU device plugin needs additional time to enumerate GPUs and advertise them to the Kubernetes scheduler after the HTTP endpoint becomes healthy. The 5-second sleep is not enough, sosandbox create --gpuis issued while the gateway has no allocatable GPU resources yet →FailedPrecondition.Bug 3 — Stale port 18789 forward silently blocks new sandbox dashboard
File:
bin/lib/onboard.js:207A prior onboard attempt (e.g. using the default
my-assistantname) leaves port 18789 forwarded to the old sandbox. When the new sandbox tries to claim the same port,openshell forward startfails. TheignoreError: truesilently swallows the error, and the new sandbox's web dashboard is never reachable onlocalhost:18789.Fix
1.
set -o pipefailon sandbox create commandNow if
openshell sandbox createexits non-zero,run()detects it and exits with an actionable error instead of continuing into a broken state.2. Poll for GPU allocatability before sandbox creation
After the gateway health check, if
gpu.nimCapableis true, the onboarder now pollsopenshell gateway info(up to 12 × 10s = 2 minutes) waiting for the GPU device plugin to register resources. If GPUs become allocatable, it proceeds confidently. If the timeout expires, it emits a warning and proceeds anyway (thepipefailfix then catches any subsequent failure cleanly).3. Stop stale port 18789 forward before claiming it
Any port 18789 forward from a previous onboard is released first, ensuring the new sandbox's dashboard is always reachable.
Failure Mode Walkthrough (Before vs After)
sandbox create --gpufailsawk; "✓ Sandbox created" printedpipefailsurfaces the error; process exits with clear messageTesting
Reproduce with a DGX (or any NVIDIA GPU host) by running
./install.shimmediately after gateway start to trigger the device plugin race. With this fix:openshellexit propagates when piped throughawkFailedPreconditionerror in all observed DGX runsopenshell forward stopis idempotent (|| true) so it's safe on first-ever runs tooFiles Changed
bin/lib/onboard.js— all three fixes