Skip to content

fix(onboard): stop the gateway when its sandbox-bridge probe fails (#5513) - #5536

Closed
abhi-0906 wants to merge 6 commits into
NVIDIA:mainfrom
abhi-0906:fix/orphaned-gateway-cleanup-on-probe-failure
Closed

fix(onboard): stop the gateway when its sandbox-bridge probe fails (#5513)#5536
abhi-0906 wants to merge 6 commits into
NVIDIA:mainfrom
abhi-0906:fix/orphaned-gateway-cleanup-on-probe-failure

Conversation

@abhi-0906

@abhi-0906 abhi-0906 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Cleanup-only follow-up to #5754 (the merged Docker Desktop/WSL host-gateway retry fix that closed #5513). This PR does not try to re-implement the primary WSL reachability fix; it covers the orphaned-gateway aftermath that can still happen on any genuine sandbox-bridge failure. When onboard's [2/8] sandbox-bridge reachability probe fails, NemoClaw aborts via process.exit(1) without stopping the OpenShell gateway it started (or reused/adopted) earlier in the same run. The gateway is left running, bound to the loopback address — so the accompanying "restart Docker and re-run" hint is misleading: the stale listener survives a Docker restart and collides with the next attempt (the orphaned-gateway symptom called out in #5513).

Fix

  • Add an onUnreachable hook to verifySandboxBridgeGatewayReachableOrExit that fires only on a genuine unreachable result — not the soft probe_unavailable skip, and not a successful probe.
  • Wire it at the three host-mode gateway paths in startDockerDriverGateway (fresh start, reuse, adopt) to tear the gateway down via the existing stopDockerDriverGatewayProcess(). That helper reads the pid file written in every path and only terminates a verified gateway process, so it is a safe no-op otherwise.

Relationship to #5754 / #5513: #5754 is the merged source fix for the Docker Desktop/WSL reachability race and closed #5513. This PR intentionally stays narrower: it ensures that any genuine probe failure — on any host — no longer orphans the gateway, and makes the "re-run onboard" guidance accurate.

Testing

  • New unit tests in gateway-sandbox-reachability.test.ts: onUnreachable fires on a genuine unreachable probe, and not on a successful probe or a soft probe_unavailable result.
  • tsc -p tsconfig.src.json clean; reachability + onboard-runtime suites pass (remaining failures are pre-existing Windows-only path / CLI-not-found tests, identical on main).

Refs #5513.

Summary by CodeRabbit

Bug Fixes

  • Improved onboarding behavior when sandbox-bridge reachability fails: the system now triggers a cleanup step before aborting, preventing leftover/reused gateway processes from remaining active.

Tests

  • Added coverage for gateway reachability verification, including ensuring the new “unreachable” handler runs for genuine failures but not for successful or soft “probe unavailable” outcomes.

Signed-off-by: Abhimanyu Kumar abhimanyukumar7290@gmail.com

@copy-pr-bot

copy-pr-bot Bot commented Jun 17, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds an optional onUnreachable callback to SandboxBridgeVerifierOptions that fires immediately before verifySandboxBridgeGatewayReachableOrExit aborts on genuine probe failure. A shared sandboxBridgeProbeOptions object is defined in startDockerDriverGateway() with a callback that stops the Docker-driver gateway process, then wired into all three gateway verification paths (reuse, adopt, healthy). Tests validate the callback's invocation semantics.

Changes

Gateway orphan cleanup on sandbox-bridge unreachability

Layer / File(s) Summary
onUnreachable callback contract
src/lib/onboard/gateway-sandbox-reachability.ts
SandboxBridgeVerifierOptions gains onUnreachable?: () => void; the function invokes it before aborting on genuine reachability failures, skipping it for probe_unavailable soft results.
Shared probe options and wiring into three gateway verification paths
src/lib/onboard.ts
Defines sandboxBridgeProbeOptions object with skip and onUnreachable callback (that stops the Docker-driver gateway process), then passes it to verifySandboxBridgeGatewayReachableOrExit in the reuse, adopt, and healthy-probe verification call sites.
Unit tests for callback semantics
src/lib/onboard/gateway-sandbox-reachability.test.ts
Three new tests assert onUnreachable fires before abort for TCP failure, is not called on success, and is not called for probe_unavailable.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

Suggested labels

bug-fix, area: onboarding

Suggested reviewers

  • cv
  • ericksoa

🐇 A gateway left open — no more!
With a callback that knocks on the door,
If the bridge can't be found,
We shut the thing down,
And leave no lost process to snore. 🌉✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the main change: adding logic to stop the gateway process when the sandbox-bridge reachability probe fails during onboarding.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/onboard.ts`:
- Around line 2193-2206: The src/lib/onboard.ts file has exceeded the growth
budget with a net addition of 17 lines, blocking the CI guardrail. To fix this,
reduce the net additions by either condensing the lengthy inline comment block
(the "// `#5513`:" explanation) that precedes the stopGatewayStartedDuringOnboard
function definition, or move the helper function and its supporting
documentation to a separate utility file. Focus on compressing the explanatory
text while preserving the essential logic and functionality of the
stopGatewayStartedDuringOnboard implementation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 841e023b-2b23-41d5-9288-3a50f900392a

📥 Commits

Reviewing files that changed from the base of the PR and between 01e5525 and 8aa9e98.

📒 Files selected for processing (3)
  • src/lib/onboard.ts
  • src/lib/onboard/gateway-sandbox-reachability.test.ts
  • src/lib/onboard/gateway-sandbox-reachability.ts

Comment thread src/lib/onboard.ts Outdated

@prekshivyas prekshivyas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. `onUnreachable` injects at a single point before the abort, all three host-mode gateway paths share it via `sandboxBridgeProbeOptions`, and `stopDockerDriverGatewayProcess` is synchronous so no async-discard risk. Tests cover genuine-unreachable, successful probe, and soft `probe_unavailable` — exactly the right three cases.

@cv cv added v0.0.67 and removed v0.0.66 labels Jun 23, 2026
@wscurran wscurran added area: networking DNS, proxy, TLS, ports, host aliases, or connectivity area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow bug-fix PR fixes a bug or regression platform: wsl Affects Windows Subsystem for Linux labels Jun 23, 2026
@wscurran

Copy link
Copy Markdown
Contributor

✨ Thanks for the proposed fix adding an onUnreachable hook to stop the gateway when the sandbox-bridge probe fails during onboarding. This proposes a way to tear down the OpenShell gateway via stopDockerDriverGatewayProcess at the three host-mode gateway paths so stale listeners don't survive Docker restarts.


Related open PRs:


Related open issues:

@cv

cv commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Manual PR Review Advisor result

This PR Review Advisor analysis was run manually via workflow_dispatch, so the workflow did not post its usual sticky comment. Posting the advisor summary here to populate the PR with advisor feedback.

Run: https://github.com/NVIDIA/NemoClaw/actions/runs/28210492266

Recommendation: merge_after_fixes (medium confidence; findings: 4)

The cleanup hook is well targeted for the direct standalone gateway paths, but the package-managed gateway path still probes without cleanup and the verifier can mask the original fatal probe error if cleanup throws.


PR Review Advisor

The cleanup hook is well targeted for the direct standalone gateway paths, but the package-managed gateway path still probes without cleanup and the verifier can mask the original fatal probe error if cleanup throws.

Required before merge

  • Package-managed gateway startup still probes without orphan cleanup (src/lib/onboard.ts:2199): The new sandboxBridgeProbeOptions object is only used by the three direct calls in startDockerDriverGateway. The earlier startPackageManagedDockerDriverGatewayWithEnvOverride path still receives only skipSandboxBridgeReachability plus the verifier function, and startPackageManagedDockerDriverGateway later calls verifySandboxBridgeGatewayReachableOrExit(exitOnFailure, { skip }) after starting the upstream user service. That path also clears runtime files before probing, so a hard sandbox-bridge failure can still leave a just-started package-managed gateway service running without the new onUnreachable cleanup.
    • Impact: The PR's core promise is not complete: onboarding can still abort on a genuine sandbox-bridge failure while leaving an OpenShell gateway running, keeping the misleading restart-and-rerun behavior and leaving an auth-disabled loopback gateway process/service alive.
    • Recommendation: Thread an explicit cleanup/stop callback through the package-managed service path as well, or add code and tests that prove package-managed gateways cannot be orphaned or are intentionally out of scope. If the service path needs different cleanup than stopDockerDriverGatewayProcess, add that service-specific cleanup at the same fatal probe boundary.
    • Verification hint: Read src/lib/onboard.ts around the startPackageManagedDockerDriverGatewayWithEnvOverride call and src/lib/onboard/docker-driver-gateway-service.ts around its healthy branch; confirm the verifier options passed there contain only { skip: skipSandboxBridgeReachability } and no cleanup callback.
    • Missing regression test: Add a test for startPackageManagedDockerDriverGateway where the user service starts and becomes healthy, verifySandboxBridgeGatewayReachableOrExit rejects for a hard probe failure, and the expected cleanup/stop callback is invoked before the failure is returned.
    • Evidence: onboard.ts constructs { skip, onUnreachable: stopDockerDriverGatewayProcess }, but does not pass that object into startPackageManagedDockerDriverGatewayWithEnvOverride; the service implementation invokes the verifier with only { skip: skipSandboxBridgeReachability }.

Resolve or justify before merge

  • Source-of-truth review needed: Sandbox-bridge unreachable cleanup after gateway startup: The advisor marked localized patch analysis as needs_followup.
    • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Verification hint: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
    • Missing regression test: Current tests prove only verifier-level callback behavior. A source-boundary regression test is still needed to prove every gateway-creating path that can hit a hard probe failure supplies or performs cleanup.
    • Evidence: Direct calls in startDockerDriverGateway use sandboxBridgeProbeOptions; the package-managed service path invokes the verifier with only { skip }.
  • Cleanup callback can mask the original fatal reachability failure (src/lib/onboard/gateway-sandbox-reachability.ts:551): options.onUnreachable?.() is invoked directly between logging the fatal unreachable message and the existing process.exit(1) / throw behavior. If the callback throws, the verifier will surface the cleanup exception instead of the sandbox-bridge unreachable failure and, in exitOnFailure mode, can skip the intended process.exit(1) path.
    • Impact: A cleanup failure in sandbox lifecycle code can make onboarding report the wrong cause and leave operators without the actionable reachability remediation. It also makes the verifier API fragile for future cleanup callbacks that are not as defensive as the current stop helper.
    • Recommendation: Treat onUnreachable as best-effort: wrap it in try/catch, warn if cleanup fails, and continue to preserve the original fatal reachability behavior.
    • Verification hint: Read verifySandboxBridgeGatewayReachableOrExit after console.error(message) and confirm the callback is invoked without a guard before process.exit(1) / throw.
    • Missing regression test: Add a verifier test where reachabilityImpl returns a hard unreachable result and onUnreachable throws; assert that the final failure still reports Docker-driver sandbox-bridge unreachable and that a cleanup warning is emitted.
    • Evidence: The changed verifier calls options.onUnreachable?.(); directly at the fatal boundary with no try/catch.
  • Linked issue's primary WSL reachability fix is not in this PR (src/lib/onboard.ts:2192): The linked issue's expected result says: "On Docker Desktop WSL, the OpenShell gateway should bind to an interface reachable from sandbox containers via host.openshell.internal:host-gateway — either 0.0.0.0:8080 or the Docker Desktop bridge interface. The sandbox-bridge probe should succeed and onboard should proceed to [3/8]." This patch does not change bind-address selection, host-gateway readiness, or retry behavior; it only cleans up after a fatal probe failure.
    • Impact: If this PR is treated as resolving [WSL2][Policy&Network] OpenShell gateway unreachable from sandbox containers on Docker Desktop WSL (binds to 127.0.0.1:8080) #5513 by itself, Docker Desktop WSL users can still fail at [2/8]; the change only reduces the orphaned-gateway aftermath. There is also active overlapping work on the same linked issue and reachability files, so the intended source-of-truth fix needs coordination.
    • Recommendation: Keep the PR scoped as an orphan-cleanup follow-up and avoid marking the linked issue resolved by this patch alone, or include the actual WSL reachability source fix/retry if this PR is meant to close [WSL2][Policy&Network] OpenShell gateway unreachable from sandbox containers on Docker Desktop WSL (binds to 127.0.0.1:8080) #5513. Reconcile behavior with the overlapping reachability PR before merge.
    • Verification hint: Diff-search the changed files for GATEWAY_BIND_ADDRESS, WILDCARD_GATEWAY_BIND_ADDRESS, Docker Desktop WSL detection, or retry-loop changes; the current diff only adds the cleanup hook and tests.
    • Missing regression test: If this PR is intended to satisfy the linked issue, add a behavior test for Docker Desktop WSL route modeling where the gateway bind/retry path makes host.openshell.internal:host-gateway reachable and onboarding proceeds past the sandbox-bridge probe.
    • Evidence: Changed files do not modify gateway bind address or retry logic; drift context shows an overlapping open PR touching the same reachability files for the same linked issue.

In-scope improvements

  • None.

Test follow-ups to resolve or justify

  • Runtime validation — Add startPackageManagedDockerDriverGateway cleans up the user-service gateway when the sandbox-bridge verifier rejects after healthy startup.. The changed behavior is in onboarding, gateway process lifecycle, and sandbox reachability boundaries. Unit coverage was added for the verifier hook, but caller/callee contract coverage and targeted runtime validation would materially improve confidence.
  • Runtime validation — Add startDockerDriverGateway passes onUnreachable cleanup for pid-file reuse, port-listener adoption, and fresh child-ready paths using mocked gateway readiness/probe seams.. The changed behavior is in onboarding, gateway process lifecycle, and sandbox reachability boundaries. Unit coverage was added for the verifier hook, but caller/callee contract coverage and targeted runtime validation would materially improve confidence.
  • Runtime validation — Add verifySandboxBridgeGatewayReachableOrExit invokes onUnreachable after UFW auto-apply succeeds but the re-probe still fails.. The changed behavior is in onboarding, gateway process lifecycle, and sandbox reachability boundaries. Unit coverage was added for the verifier hook, but caller/callee contract coverage and targeted runtime validation would materially improve confidence.
  • Runtime validation — Add verifySandboxBridgeGatewayReachableOrExit preserves the sandbox-bridge unreachable failure and logs cleanup failure when onUnreachable throws.. The changed behavior is in onboarding, gateway process lifecycle, and sandbox reachability boundaries. Unit coverage was added for the verifier hook, but caller/callee contract coverage and targeted runtime validation would materially improve confidence.
  • Runtime validation — Perform targeted runtime validation that a hard sandbox-bridge probe failure after gateway startup leaves no OpenShell gateway listener/process for both standalone and package-managed startup modes.. The changed behavior is in onboarding, gateway process lifecycle, and sandbox reachability boundaries. Unit coverage was added for the verifier hook, but caller/callee contract coverage and targeted runtime validation would materially improve confidence.
  • Acceptance clause: Issue title: "[WSL2][Policy&Network] OpenShell gateway unreachable from sandbox containers on Docker Desktop WSL (binds to 127.0.0.1:8080)" — add test evidence or identify existing coverage. This PR addresses the orphaned-gateway aftermath of a failed reachability probe, but it does not change the Docker Desktop WSL bind address or make the sandbox route reachable.
  • Acceptance clause: Expected Result: "On Docker Desktop WSL, the OpenShell gateway should bind to an interface reachable from sandbox containers via host.openshell.internal:host-gateway — either 0.0.0.0:8080 or the Docker Desktop bridge interface. The sandbox-bridge probe should succeed and onboard should proceed to [3/8]." — add test evidence or identify existing coverage. No changed code updates gateway bind-address selection, Docker Desktop bridge detection, or retry behavior.
  • Acceptance clause: Actual Result: "Onboard aborts. The gateway process is left running on the host, still bound to 127.0.0.1:8080 — so restarting Docker does not fix it (the restart-and-rerun hint is misleading on this platform)." — add test evidence or identify existing coverage. The three direct standalone gateway probe calls now pass onUnreachable: stopDockerDriverGatewayProcess, but the package-managed user-service startup path still probes without an onUnreachable cleanup callback.

What looks good

  • The new verifier tests cover the key positive and negative callback conditions: hard unreachable calls cleanup, success does not, and soft probe_unavailable does not.
  • The cleanup callback reuses stopDockerDriverGatewayProcess, which verifies the stored PID is an OpenShell gateway process before terminating it.
  • The patch is small and avoids adding new runners, dependencies, workflow changes, or broad abstractions.

cv pushed a commit that referenced this pull request Jun 26, 2026
…#5512) (#5541)

## Summary

Follow-up to #5537 addressing the orphan-backup symptom in #5512. When
the Docker GPU patch's recreate `docker run` fails **after** the
original sandbox was already renamed to
`*-nemoclaw-gpu-backup-<timestamp>`, the early-failure path removed only
the failed *new* container and left the backup orphaned — stranding the
sandbox with no live original, and colliding with
`*-nemoclaw-gpu-backup-*` on the next retry (as reported in #5512).

The supervisor-reconnect failure path already rolls back to the backup;
this path didn't.

## Fix

Reuse the existing rollback primitive (`rollbackToBackupContainer`) on
the early-failure path: remove the failed new container, rename the
backup back to the original name, and start it — restoring the pre-patch
sandbox instead of leaking a backup container.

- Adds `rollbackDockerGpuPatchOnRecreateFailure(refs, deps)` to
`docker-gpu-patch-finalize.ts`, which resolves the real `docker start` /
`docker rename` defaults (the recreate call path only carries a deps
subset, so `dockerStart` would otherwise be unset).
- Records `context.rolledBack` for failure diagnostics, matching the
reconnect-failure path.
- No `onboard.ts` change; all edits are under `src/lib/onboard/`.

## Testing

- New composed test in `docker-gpu-patch-rollback.test.ts`: when
`dockerRunDetached` fails, the backup is renamed back to the original
and started, and is never left as an orphaned container.
- `tsc -p tsconfig.src.json` clean; rollback / finalize / sandbox-create
suites pass (18/18).

## Relationship to the WSL Docker Desktop chain

- #5534 — gateway bind at `[2/8]`
- #5536 — gateway cleanup on probe failure
- #5537 — skip CDI GPU mode at `[6/8]` (makes the patch succeed on
Docker Desktop WSL, so this early-failure path is no longer hit there)
- this PR — restore the pre-patch sandbox for any *other* early
GPU-recreate failure

Refs #5512.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Improved recovery for Docker GPU patch recreation failures: if the
GPU-enabled recreate step fails after the original container is renamed,
the system now performs a reliable rollback to the pre-patch sandbox
state and cleans up the failed recreate attempt.

* **Tests**
* Added a rollback-path test for a recreate-phase `docker run --detach`
failure, verifying restoration of the original container name, restart
behavior, and correct cleanup (including ignoring the failed recreated
container).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Abhimanyu Kumar <abhimanyukumar7290@gmail.com>

---------

Signed-off-by: Abhimanyu Kumar <abhimanyukumar7290@gmail.com>
Signed-off-by: Preksha Vyas <prekshiv@nvidia.com>
Co-authored-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Julie Yaunches <jyaunches@nvidia.com>
@cv cv removed the v0.0.69 label Jun 28, 2026
@jyaunches
jyaunches force-pushed the fix/orphaned-gateway-cleanup-on-probe-failure branch 2 times, most recently from 4dbc7dc to f045b25 Compare July 1, 2026 21:07
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ❌ Some jobs failed

Run: 28548630243
Workflow ref: ci/pr-5536-e2e
Requested targets: (selector rejected by workflow validation)
Requested jobs: (selector rejected by workflow validation)
Summary: 0 passed, 1 failed, 0 cancelled, 0 skipped

Job Result
generate-matrix ❌ failure

Failed jobs: generate-matrix. Check run artifacts for logs.

@jyaunches
jyaunches force-pushed the fix/orphaned-gateway-cleanup-on-probe-failure branch from f045b25 to 2276e65 Compare July 1, 2026 21:30
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All selected jobs passed

Run: 28548713900
Workflow ref: ci/pr-5536-e2e
Requested targets: ubuntu-repo-cloud-openclaw
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected)
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
live ✅ success

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ⚠️ Run cancelled — no signal

Run: 28548713855
Workflow ref: ci/pr-5536-e2e
Requested targets: (default — all supported)
Requested jobs: cloud-onboard,sandbox-operations
Summary: 0 passed, 0 failed, 2 cancelled, 0 skipped

Job Result
cloud-onboard ⚠️ cancelled
sandbox-operations ⚠️ cancelled

@jyaunches
jyaunches force-pushed the fix/orphaned-gateway-cleanup-on-probe-failure branch 5 times, most recently from 81819ad to e7a80eb Compare July 1, 2026 22:51
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ⚠️ Run cancelled — no signal

Run: 28553303096
Workflow ref: ci/pr-5536-e2e
Requested targets: ubuntu-repo-cloud-openclaw
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected)
Summary: 0 passed, 0 failed, 1 cancelled, 0 skipped

Job Result
live ⚠️ cancelled

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ⚠️ Run cancelled — no signal

Run: 28553301987
Workflow ref: ci/pr-5536-e2e
Requested targets: (default — all supported)
Requested jobs: cloud-onboard,gateway-health-honest,openshell-gateway-auth-contract
Summary: 0 passed, 0 failed, 3 cancelled, 0 skipped

Job Result
cloud-onboard ⚠️ cancelled
gateway-health-honest ⚠️ cancelled
openshell-gateway-auth-contract ⚠️ cancelled

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All selected jobs passed

Run: 28553374003
Workflow ref: ci/pr-5536-e2e-e7a80eb
Requested targets: ubuntu-repo-cloud-openclaw
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected)
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
live ✅ success

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All requested jobs passed

Run: 28553372297
Workflow ref: ci/pr-5536-e2e-e7a80eb
Requested targets: (default — all supported)
Requested jobs: cloud-onboard,gateway-health-honest,openshell-gateway-auth-contract
Summary: 3 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success
gateway-health-honest ✅ success
openshell-gateway-auth-contract ✅ success

@jyaunches
jyaunches enabled auto-merge (squash) July 1, 2026 23:11
@jyaunches
jyaunches force-pushed the fix/orphaned-gateway-cleanup-on-probe-failure branch from e7a80eb to 2dd54b8 Compare July 1, 2026 23:29
@jyaunches
jyaunches disabled auto-merge July 1, 2026 23:31
abhi-0906 and others added 6 commits July 2, 2026 08:48
…VIDIA#5513)

When onboard's [2/8] sandbox-bridge reachability probe fails, NemoClaw
aborts via process.exit(1) without stopping the OpenShell gateway it
started (or reused/adopted) earlier in the same run. The gateway is left
running, bound to the loopback address, so the accompanying "restart
Docker and re-run" hint is misleading: the stale listener survives a
Docker restart and collides with the next attempt.

Add an onUnreachable hook to verifySandboxBridgeGatewayReachableOrExit
that fires only on a genuine unreachable result (not the soft
probe_unavailable skip or a successful probe), and wire it at the three
host-mode gateway paths in startDockerDriverGateway (fresh start, reuse,
adopt) to tear the gateway down via the existing
stopDockerDriverGatewayProcess(). That helper reads the pid file written
in every path and only terminates a verified gateway process, so it is a
safe no-op otherwise.

Follow-up to the bind-address fix in NVIDIA#5534: that change keeps the probe
from failing on Docker Desktop WSL in the first place, while this ensures
any genuine probe failure no longer orphans the gateway.

Signed-off-by: Abhimanyu Kumar <abhimanyukumar7290@gmail.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
@prekshivyas

Copy link
Copy Markdown
Collaborator

Closing as superseded. The target bug #5513 was fixed and closed by #5754 (fix(onboard): retry Docker Desktop gateway bridge probe, merged 2026-06-28) — which took the retry approach to the same sandbox↔host gateway-bridge probe failure. This PR's alternative "stop the gateway on probe failure" approach is no longer needed, and the branch is ~79 commits behind main.

Thanks @abhi-0906 for the fix — the underlying issue is resolved via #5754. Reopen if you think there's a case #5754 doesn't cover.

@prekshivyas prekshivyas closed this Jul 5, 2026
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
…NVIDIA#5512) (NVIDIA#5541)

## Summary

Follow-up to NVIDIA#5537 addressing the orphan-backup symptom in NVIDIA#5512. When
the Docker GPU patch's recreate `docker run` fails **after** the
original sandbox was already renamed to
`*-nemoclaw-gpu-backup-<timestamp>`, the early-failure path removed only
the failed *new* container and left the backup orphaned — stranding the
sandbox with no live original, and colliding with
`*-nemoclaw-gpu-backup-*` on the next retry (as reported in NVIDIA#5512).

The supervisor-reconnect failure path already rolls back to the backup;
this path didn't.

## Fix

Reuse the existing rollback primitive (`rollbackToBackupContainer`) on
the early-failure path: remove the failed new container, rename the
backup back to the original name, and start it — restoring the pre-patch
sandbox instead of leaking a backup container.

- Adds `rollbackDockerGpuPatchOnRecreateFailure(refs, deps)` to
`docker-gpu-patch-finalize.ts`, which resolves the real `docker start` /
`docker rename` defaults (the recreate call path only carries a deps
subset, so `dockerStart` would otherwise be unset).
- Records `context.rolledBack` for failure diagnostics, matching the
reconnect-failure path.
- No `onboard.ts` change; all edits are under `src/lib/onboard/`.

## Testing

- New composed test in `docker-gpu-patch-rollback.test.ts`: when
`dockerRunDetached` fails, the backup is renamed back to the original
and started, and is never left as an orphaned container.
- `tsc -p tsconfig.src.json` clean; rollback / finalize / sandbox-create
suites pass (18/18).

## Relationship to the WSL Docker Desktop chain

- NVIDIA#5534 — gateway bind at `[2/8]`
- NVIDIA#5536 — gateway cleanup on probe failure
- NVIDIA#5537 — skip CDI GPU mode at `[6/8]` (makes the patch succeed on
Docker Desktop WSL, so this early-failure path is no longer hit there)
- this PR — restore the pre-patch sandbox for any *other* early
GPU-recreate failure

Refs NVIDIA#5512.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Improved recovery for Docker GPU patch recreation failures: if the
GPU-enabled recreate step fails after the original container is renamed,
the system now performs a reliable rollback to the pre-patch sandbox
state and cleans up the failed recreate attempt.

* **Tests**
* Added a rollback-path test for a recreate-phase `docker run --detach`
failure, verifying restoration of the original container name, restart
behavior, and correct cleanup (including ignoring the failed recreated
container).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Abhimanyu Kumar <abhimanyukumar7290@gmail.com>

---------

Signed-off-by: Abhimanyu Kumar <abhimanyukumar7290@gmail.com>
Signed-off-by: Preksha Vyas <prekshiv@nvidia.com>
Co-authored-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Julie Yaunches <jyaunches@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: networking DNS, proxy, TLS, ports, host aliases, or connectivity area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow bug-fix PR fixes a bug or regression platform: wsl Affects Windows Subsystem for Linux

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[WSL2][Policy&Network] OpenShell gateway unreachable from sandbox containers on Docker Desktop WSL (binds to 127.0.0.1:8080)

5 participants