fix(sandbox): recover a gateway wedged in any not-serving state - #8092
Conversation
The in-sandbox serving watchdog only ever escalated on curl exit 7, so a
gateway whose process stayed alive while its listener became unusable was
recovered in exactly one shape: an unbroken streak of pure connection-refused
probes. Every other wedge signature read as "a listener exists" and silently
re-armed the watchdog:
* curl 28 - the socket accepts but nothing answers within the timeout
* curl 52/56 - accepted then dropped, which is the 1006 abnormal-closure
transport error surfaced by 'openclaw health'
* curl 0 with an HTTP error status - /health replies but no session serves
Those outcomes were delegated to the Docker HEALTHCHECK, but nothing restarts
an unhealthy OpenShell sandbox container, so the gateway stayed wedged. A
wedge that alternated between refused and any other failure also reset the
consecutive-refusal counter on every other probe and never reached the
threshold at all, leaving a live watchdog that logged nothing and recovered
nothing.
Classify each probe with the same definition the boot-time readiness gate
uses - /health must answer 200 or 401 - and count every not-serving outcome
toward one threshold. Probes that fail for local reasons (curl missing or
otherwise unable to run) stay inconclusive: they neither arm the watchdog nor
count toward the threshold, so a broken probe can never become a kill loop.
Each failed probe now logs the cause it observed.
Arming after the first serving probe, the PID-identity and cmdline checks
before signalling, and the respawn-marker handshake are unchanged. The
watchdog suite moves to its own file with the shared shell-harness helpers
extracted, keeping both inside the test-file size budget.
Fixes NVIDIA#7377
Signed-off-by: Tony Luo <xialuo@nvidia.com>
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe gateway watchdog now classifies health probes, tracks consecutive not-serving results, and triggers supervised gateway recovery. Tests cover probe outcomes, thresholds, PID identity, process replacement, and restart races. Troubleshooting guidance documents the updated behavior. ChangesGateway watchdog recovery
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Watchdog
participant curl
participant OpenClawGateway
participant Supervisor
Watchdog->>curl: Probe local health endpoint
curl->>OpenClawGateway: Send health request
OpenClawGateway-->>curl: Return HTTP status or transport result
curl-->>Watchdog: Return classified probe result
Watchdog->>Watchdog: Count consecutive not-serving probes
Watchdog->>OpenClawGateway: Terminate identity-validated gateway
Supervisor->>OpenClawGateway: Relaunch gateway
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
PR Review Advisor — No blocking findings reportedAdvisor assessment: No blocking advisor findings reported Model lanes
3 terminology differences from the second opinionAdvisory only. These are normalized differences from the primary terminology receipt.
2 additional E2E selections from the second opinionAdvisory only. The primary lane did not select these E2E jobs or targets.
Second-opinion terminology and E2E selections are advisory. They do not change the primary assessment or E2E / PR Gate. 3 semantic terminology decisionsTerminology decisions are advisory. They affect the assessment only when a separate finding identifies concrete semantic impact.
E2E guidanceAdvisory only. E2E / PR Gate selects and runs jobs independently. Recommended E2E: 1 optional E2E recommendation
This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge. |
Address PR Review Advisor warnings on the gateway serving watchdog:
* cover curl exit 55 (send error), which the probe classifier treats as
not serving but the parameterized recovery table omitted
* prove that an inconclusive probe carries an armed streak rather than
clearing it, so an intermittent local probe failure cannot postpone
recovery indefinitely
* name the source boundary the watchdog compensates for and the condition
that permits removing it, in both the script comment and the
troubleshooting page
* define the embedded fallback where the troubleshooting page first uses it
Signed-off-by: Tony Luo <xialuo@nvidia.com>
Address the remaining PR Review Advisor warnings:
* add a harness case that starts the watchdog with an empty PATH, so the
`command -v curl` guard sees no probe command at all. This is a distinct
path from a probe that runs and fails, and removing the guard makes the
new case fail.
* correct the troubleshooting page: the watchdog and the startup wait share
the 200-or-401 response requirement, but the startup path additionally
verifies listener ownership, so they are not the same check.
Signed-off-by: Tony Luo <xialuo@nvidia.com>
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
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 `@docs/reference/troubleshooting.mdx`:
- Line 648: Update the troubleshooting sentence around the
gateway_transport_error description to remove both em dashes, replacing them
with guideline-compliant punctuation while preserving the existing meaning and
inline code formatting.
🪄 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: 5eb7388f-dc10-44bd-ace6-abd68060d04c
📒 Files selected for processing (5)
docs/reference/troubleshooting.mdxscripts/nemoclaw-start.shtest/gateway-serving-watchdog.test.tstest/nemoclaw-start-gateway-health.test.tstest/nemoclaw-start-gateway.test-helpers.ts
extractGatewayLogAppendFunction moved to the watchdog suite with its only caller, leaving an unused import behind. Flagged by CodeQL. Signed-off-by: Tony Luo <xialuo@nvidia.com>
The writing guide in docs/CONTRIBUTING.md prefers commas, colons, or separate sentences. Flagged by CodeRabbit. Signed-off-by: Tony Luo <xialuo@nvidia.com>
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
Both automated review findings are addressed:
All checks now pass. The earlier Both advisor lanes report 0 blockers, 0 warnings, 0 suggestions. |
|
CI status update after the base moved forward. Three checks went red on the latest run. Two were transient and cleared on a re-run with no code change:
That leaves Current tally: 45 passing, 1 failing on that advisor lane. A maintainer needs to decide whether to accept it; I have restored the corresponding Quality Gates line in the description rather than marking it resolved. Note: this branch is behind |
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Security review: PASSVerdictPASS for commit Findings tableThe review found no findings. Detailed analysis
Files reviewed
GitHub CI is authoritative for validation. I did not run a duplicate local test suite; the normal commit and pre-push hooks passed, including repository checks, ShellCheck, secret scanning, formatting, and CLI TypeScript validation. |
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Merge current main and preserve contributor attribution. Align diagnostics, tests, comments, and troubleshooting guidance with serving behavior. Signed-off-by: Carlos Villela <cvillela@nvidia.com>
apurvvkumaria
left a comment
There was a problem hiding this comment.
Reviewed current head c1e3c19. The runtime behavior is safe: arming requires HTTP 200 or 401, transport failures remain not-serving, unknown probe failures stay inconclusive, and PID identity plus command line are rechecked before signaling. Required CI and E2E pass, so this is safe to merge.\n\nNon-blocking fast-follow: the swap-test curl stub in test/gateway-serving-watchdog.test.ts returns success without printing an HTTP status, so the classifier sees HTTP 000 and the test does not actually exercise per-PID armed-state reset. Please narrowly follow up by printing 200 in the success branch or reusing the status-aware curl-plan stub. This is a test-confidence improvement, not a merge blocker.
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
apurvvkumaria
left a comment
There was a problem hiding this comment.
Reviewed exact head 47accd8. The runtime and documentation behavior remain unchanged from the prior review. The only PR-specific follow-up makes the PID-swap test emit HTTP 200, so it now genuinely exercises per-PID watchdog state reset. The focused watchdog suite passes 18 of 18 tests. Current unrelated CI failures reproduce in files identical to the current base; no blocking correctness, security, regression, or compatibility defect is attributable to this PR.
|
Branch refreshed on current Current CI has three distinct failures, none of them from the watchdog change. This branch touches only 1. 2. 3. Previously transient, now green. Both |
<!-- markdownlint-disable MD041 --> ## Summary Prepares the canonical v0.0.102 release documentation from the current release-labeled scope. The change adds a dated changelog for all 38 user-facing shipping PRs and corrects the OpenClaw agent command reference for the behavior delivered by #8191. ## Changes - Add `docs/changelog/2026-08-04.mdx` with the v0.0.102 release summary, detailed behavior changes, support boundaries, security evidence links, and links to durable documentation. - Update `docs/reference/commands.mdx` to describe non-JSON OpenClaw output capture, its combined limit, marker handling, stream suppression, recovery guidance, and exit behavior. - [#8167](#8167) -> `docs/changelog/2026-08-04.mdx`: Records authenticated attachment of operator-managed llama.cpp servers. - [#8129](#8129) -> `docs/changelog/2026-08-04.mdx`: Records the Experimental managed vLLM profile for two DGX Spark systems. - [#7983](#7983) -> `docs/changelog/2026-08-04.mdx`: Records qualification of the May 2026 GB300WS factory image. - [#8207](#8207) -> `docs/changelog/2026-08-04.mdx`: Records the qualified DGX Station driver transaction. - [#8208](#8208) -> `docs/changelog/2026-08-04.mdx`: Records mode-bound Express resume state. - [#8158](#8158) -> `docs/changelog/2026-08-04.mdx`: Records recovery of host-global dual-Station runtime ownership. - [#8145](#8145) -> `docs/changelog/2026-08-04.mdx`: Records Windows-host Ollama validation from Docker Desktop's network context. - [#8190](#8190) -> `docs/changelog/2026-08-04.mdx`: Records HTTP model pulls when WSL has no local Ollama executable. - [#8195](#8195) -> `docs/changelog/2026-08-04.mdx`: Records reuse of a healthy installer-managed CLI. - [#8053](#8053) -> `docs/changelog/2026-08-04.mdx`: Records early rejection of incompatible OpenShell gateway versions. - [#8098](#8098) -> `docs/changelog/2026-08-04.mdx`: Records the bounded package-service-to-standalone gateway recovery transition. - [#8216](#8216) -> `docs/changelog/2026-08-04.mdx`: Records the final dashboard port selected during multi-sandbox onboarding. - [#8146](#8146) -> `docs/changelog/2026-08-04.mdx`: Records managed startup-state restoration for stopped sandboxes. - [#8092](#8092) -> `docs/changelog/2026-08-04.mdx`: Records gateway watchdog recovery for classified not-serving states. - [#8182](#8182) -> `docs/changelog/2026-08-04.mdx`: Records consistent managed-recovery wait configuration. - [#8040](#8040) -> `docs/changelog/2026-08-04.mdx`: Records Docker sandbox rollback authority through late validation. - [#8130](#8130) -> `docs/changelog/2026-08-04.mdx`: Records bounded Shields deadline recovery and durable containment. - [#8086](#8086) -> `docs/changelog/2026-08-04.mdx`: Records repair of narrowly validated permission-only configuration drift. - [#8122](#8122) -> `docs/changelog/2026-08-04.mdx`: Records prompt failure and guidance for corrupt transition locks. - [#8124](#8124) -> `docs/changelog/2026-08-04.mdx`: Records policy restoration flags, previews, and target revalidation. - [#7886](#7886) -> `docs/changelog/2026-08-04.mdx`: Records explicit destruction after pre-delete Shields hardening failures while preserving recovery authority. - [#7901](#7901) -> `docs/changelog/2026-08-04.mdx`: Records multi-port uninstall behavior and shared-resource preservation. - [#7984](#7984) -> `docs/changelog/2026-08-04.mdx`: Records one classified transient remote MCP startup retry. - [#7954](#7954) -> `docs/changelog/2026-08-04.mdx`: Records bounded hosted-inference probe replies. - [#7574](#7574) -> `docs/changelog/2026-08-04.mdx`: Records preservation of validated reasoning capabilities through onboarding. - [#8089](#8089) -> `docs/changelog/2026-08-04.mdx`: Records proxy routing for Hermes WhatsApp pairing and media traffic. - [#7682](#7682) -> `docs/changelog/2026-08-04.mdx`: Records native Hermes session deletion and identifier validation. - [#8150](#8150) -> `docs/changelog/2026-08-04.mdx`: Records corporate CA trust for LangChain Deep Agents Code image builds. - [#8156](#8156) -> `docs/changelog/2026-08-04.mdx`: Records reviewed managed runtime dependency remediation. - [#8180](#8180) -> `docs/changelog/2026-08-04.mdx`: Records reviewed MCP discovery runtime dependency updates. - [#8196](#8196) -> `docs/changelog/2026-08-04.mdx`: Records private npm dependency remediation across managed images. - [#8203](#8203) -> `docs/changelog/2026-08-04.mdx`: Records reviewed Hermes and LangChain Deep Agents Code Python dependency updates. - [#8125](#8125) -> `docs/changelog/2026-08-04.mdx`: Records bounded diagnostics for invalid enumerated CLI values. - [#8193](#8193) -> `docs/changelog/2026-08-04.mdx`: Records bounded diagnostics for unresolved sandbox base images. - [#8118](#8118) -> `docs/changelog/2026-08-04.mdx`: Records bounded diagnostics for changed gateway authority. - [#8191](#8191) -> `docs/changelog/2026-08-04.mdx`, `docs/reference/commands.mdx`: Records output capture, marker handling, recovery guidance, and exit behavior for non-JSON OpenClaw agent commands. - [#8187](#8187) -> `docs/changelog/2026-08-04.mdx`: Records the aligned interactive-installation start across supported agents. - [#8153](#8153) -> `docs/changelog/2026-08-04.mdx`: Records current product capabilities and support boundaries. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [x] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates - [ ] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [x] Tests not applicable — justification: This documentation-only release preparation does not change executable behavior. Existing changelog and published-route tests pass. - [x] Docs updated for user-facing behavior changes - [ ] Docs not applicable — justification: - [ ] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [ ] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Documentation Writer Review - [x] Documentation writer subagent reviewed the completed changes - Result: `docs-updated` - Evidence: Independently reviewed `docs/changelog/2026-08-04.mdx` and `docs/reference/commands.mdx` at commit `b89913780`. All 38 user-facing v0.0.102 PRs are represented, #8191 behavior matches the implementation, and the writing rules, documentation style, controlled terminology, route structure, and skip policy pass review. Targeted tests pass 36/36 and the documentation build completes with 0 errors. - Agent: Codex Desktop independent documentation writer <!-- docs-review-head-sha: b899137 --> <!-- docs-review-agents-blob-sha: 3dd7c24 --> ## DGX Station Hardware Evidence - [ ] Tested on DGX Station - Tested commit: Not applicable - Station profile/scenario: Not applicable - Result: Not applicable - Supporting evidence: Not applicable ## Verification - [x] PR description includes a `Signed-off-by:` line and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run validate:pr` passed after refreshing `origin/main` when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — `npx vitest run --project integration test/changelog-docs.test.ts test/check-docs-published-routes.test.ts` passed 36/36. - [x] Applicable broad gate passed — not applicable to documentation-only changes; `npm run docs` completed successfully with 0 errors. - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) — completed with 0 errors and 2 existing Fern warnings. - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [x] New doc pages include SPDX header and frontmatter (new pages only) — the native dated changelog uses the required parser-safe MDX SPDX comment and intentionally has no frontmatter. --- Signed-off-by: Apurv Kumaria <akumaria@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Documentation** - Added release notes for v0.0.102, covering authentication, hardware setup, WSL, installer recovery, sandbox resilience, policy management, inference reliability, CLI improvements, and unified quickstarts. - Updated command documentation to explain how non-JSON agent output is collected, replayed, and reported. - **Bug Fixes** - Improved command-output recovery guidance when output exceeds limits or contains unsupported fallback markers. - Preserved accurate command exit-status reporting after output processing. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Summary
The sandbox serving watchdog previously recovered an alive but unusable OpenClaw gateway only after an uninterrupted sequence of connection-refused health probes. A listener can also become unusable when a socket accepts and stalls, accepts and drops the connection, or answers
/healthwith an error status. The watchdog treated each of those results as evidence that a listener existed. It rearmed without a log entry or recovery, so the gateway remained unable to serve. The watchdog now uses the same response requirement as the boot-time readiness check:/healthmust answer200or401. It recovers each not-serving result. It still does not act before a gateway has served or when the probe cannot run.Related Issue
Fixes #7377
Changes
scripts/nemoclaw-start.sh: addedgateway_watchdog_probe_gateway, which classifies a health probe as serving (/healthanswered200or401), not serving (refused, timed out, reset, empty reply, or an HTTP error status), or inconclusive (the probe itself could not run). The watchdog now counts every not-serving outcome toward one threshold instead of requiring consecutivecurlexit 7 results.scripts/nemoclaw-start.sh: inconclusive probes hold the watchdog's armed state and streak rather than rearming it, so a missing or failingcurlcan never escalate into a kill loop against a healthy gateway. The watchdog also exits early with a message whencurlis absent.scripts/nemoclaw-start.sh: each failed probe now logs the cause it observed, such asconnection refused,probe timeout,connection reset, orHTTP 503. An operator can distinguish a refused port from a listener that accepts connections but cannot serve.docs/reference/troubleshooting.mdx: documented the serving definition, the wedge symptoms users see (gateway_transport_error,1006 abnormal closure, containerrunningwith no restarts, replies still arriving over the embedded fallback route), and what ahealth probe inconclusiveline means.test/gateway-serving-watchdog.test.ts(new) andtest/nemoclaw-start-gateway.test-helpers.ts(new): the watchdog suite moved to its own file with the shared shell-harness helpers extracted, keeping both files insideci/test-file-size-budget.json.test/gateway-serving-watchdog.test.ts: the PID-swap regression now emits HTTP200on the predecessor's successful probe, so it proves that the replacement gateway does not inherit the predecessor's armed state.The arming rule (never act until the gateway has served at least once), the PID-identity and cmdline checks before signalling, the respawn-marker handshake, and the
NEMOCLAW_GATEWAY_WATCHDOG_*environment variable names are all unchanged.Why the reported sandboxes never recovered
The old counter required four consecutive connection-refused probes. A wedge that alternated between refused and any other failure mode reset that counter on every other probe, which is why the reporter's manual
curlshowed(7)while the watchdog had still never escalated. That path is now covered by a regression test.The non-refused outcomes were previously delegated to the Docker
HEALTHCHECK. Nothing restarts an unhealthy OpenShell sandbox container, which matches the reported "container restart count: 0" with the gateway wedged indefinitely.Type of Change
Quality Gates
e0c4d7ef9efdadfd19ec494e19edfcad8947d76aagainst basee9fb170a2e3e4c4dcfa19e398232f71b8f2bace6; all nine categories pass with no findings. The serving prerequisite, strict 200/401 classifier, inconclusive fail-safe, PID start-identity check, gateway command-line check, and signal-time identity revalidation remain intact.Documentation Writer Review
docs-updateddocs/reference/troubleshooting.mdx; verified the watchdog behavior, user-visible impact, recovery instructions, and lifecycle limits against the exact implementation and focused tests. Documentation build passed with 0 errors and 2 baseline Fern warnings.Verification
Signed-off-by:line and every commit appears asVerifiedin GitHubpre-commit,commit-msg, andpre-pushhooks passed, ornpm run validate:prpassed after refreshingorigin/mainwhen hooks were skipped or unavailable —npm run validate:prpassed at exact heade0c4d7ef9efdadfd19ec494e19edfcad8947d76a; the final maintainer commit also passed normal pre-commit and commit-msg hooks.npx vitest run --project integration test/gateway-serving-watchdog.test.ts→ 18 passed. The combined watchdog and gateway-health run passed 41 of 42 tests; the sole failure is the neighboring lock-cleanup fixture invoking GNUtimeout, which is absent on this macOS host. CI remains authoritative for the full Linux run.npm testfor broad runtime/test-harness changes;npm run checkfor repo-wide validation/coverage changes — not claimed locally. Exact-headnpm run validate:pr, CLI build, plugin build, focused tests,git diff --check, andnpm run docspassed; required GitHub CI and E2E must pass before merge.npm run docsbuilds without warnings (doc changes only) — completed with 0 errors and 2 pre-existing non-blocking Fern warnings (local Fern authentication and light-mode accent contrast).How the fix was verified against the reported failure
Each wedge signature was driven through the real watchdog loop with a scripted probe sequence and a real background process standing in for the gateway. Before the change, only the pure-refused sequence produced any output at all; timeout, reset, empty-reply, HTTP-error, and alternating sequences produced complete silence and no recovery. After the change, each not-serving sequence reaches the recovery threshold. A gateway that has not served, a
401response, a recovering gateway, and an unrunnable probe leave the gateway process running.Signed-off-by: Tony Luo xialuo@nvidia.com
Summary by CodeRabbit
Bug Fixes
Documentation
Tests