Skip to content

fix(cli): fail fast on gateway port conflicts#6759

Merged
cv merged 2 commits into
mainfrom
fix/6752-onboard-port-conflict
Jul 13, 2026
Merged

fix(cli): fail fast on gateway port conflicts#6759
cv merged 2 commits into
mainfrom
fix/6752-onboard-port-conflict

Conversation

@sandl99

@sandl99 sandl99 commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

nemoclaw onboard now checks for a clearly foreign process on the OpenShell gateway port before running gateway reuse probes. That prevents a silent listener on port 8080 from stalling onboarding and reports the conflict with the shared terminal error styling.

Related Issue

Fixes #6752

Changes

  • Add an early gateway-port conflict check after OpenShell availability is confirmed and before openshell status / gateway info probes run.
  • Preserve NemoClaw/OpenShell/Docker gateway candidates on the existing reuse path while failing fast for identifiable foreign listeners.
  • Extract gateway-port conflict classification into a focused src/lib/onboard/ helper so the top-level onboard entrypoint stays net smaller.
  • Share the port-conflict report formatting so both early and required-port failures include the styled heading, PID/process details, remediation hints, and alternate NEMOCLAW_GATEWAY_PORT guidance.
  • Bound gateway reuse status/info probes with the existing OpenShell probe timeout.
  • Add unit and integration regression coverage for styled diagnostics, probe timeouts, candidate listener classification, and the silent foreign-listener fast-fail path.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • 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:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification: existing troubleshooting and command docs already cover gateway port conflicts and NEMOCLAW_GATEWAY_PORT; no new option or workflow was added.
  • 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: self-review; the change only reorders a local port ownership check ahead of gateway probes, keeps NemoClaw/OpenShell/Docker candidate listeners on the existing reuse path, adds bounded probe timeouts, and is covered by focused regression tests.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Verification

  • PR description includes the DCO sign-off declaration and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run check:diff passed when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: npm run build:cli passed; npx vitest run --project cli src/lib/onboard/gateway-port-conflict.test.ts src/lib/onboard/gateway-stale-port-reuse.test.ts src/lib/onboard/port-conflict-report.test.ts src/lib/onboard/gateway-reuse.test.ts passed; npx vitest run --project integration test/onboard-gateway-port-conflict-fast-fail.test.ts passed; npm run typecheck:cli passed.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result: not applicable; focused CLI onboarding fix covered by targeted tests and npm run check:diff.
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: San Dang sdang@nvidia.com

Summary by CodeRabbit

  • Bug Fixes

    • Onboarding now detects gateway-port conflicts earlier and exits promptly when an unrelated process is using the configured port.
    • Port conflict messages are now consistently formatted, include blocking-process details when available, and provide clearer guidance for resolving the issue or choosing another port.
    • Gateway inspection probes now share consistent timeout handling to help prevent hangs.
  • Tests

    • Added automated coverage for port conflict reporting, gateway reuse snapshots, and fast-fail onboarding behavior under port-blocked scenarios.

@sandl99 sandl99 self-assigned this Jul 13, 2026
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Onboarding now detects foreign listeners on the configured gateway port before gateway inspection, prints a shared port-conflict report, and exits promptly. Gateway reuse probes use a bounded timeout, with unit, formatting, and integration tests covering the updated behavior.

Changes

Gateway port conflict handling

Layer / File(s) Summary
Standardized port conflict reporting
src/lib/onboard/port-conflict-report.ts, src/lib/onboard/port-conflict-report.test.ts, src/lib/onboard.ts
Adds shared port-conflict formatting and printing, tests colored and plain output, and replaces manual error output.
Bounded gateway reuse probes
src/lib/onboard/gateway-reuse.ts, src/lib/onboard/gateway-reuse.test.ts
Applies OPENSHELL_PROBE_TIMEOUT_MS to status and gateway-info probes and verifies the command options.
Foreign listener preflight fast-fail
src/lib/onboard/gateway-port-conflict.ts, src/lib/onboard/gateway-port-conflict.test.ts, src/lib/onboard.ts, test/onboard-gateway-port-conflict-fast-fail.test.ts
Classifies gateway port owners, reports foreign conflicts immediately after OpenShell setup, exits nonzero, and verifies gateway inspection is skipped.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Onboard
  participant PortProbe
  participant GatewayPortConflict
  participant PortConflictReport
  Onboard->>GatewayPortConflict: inspect configured gateway port
  GatewayPortConflict->>PortProbe: check gateway port
  PortProbe-->>GatewayPortConflict: foreign listener details
  GatewayPortConflict->>PortConflictReport: print conflict report
  GatewayPortConflict-->>Onboard: exit nonzero before gateway inspection
Loading

Possibly related PRs

  • NVIDIA/NemoClaw#4598: Both modify onboarding preflight port-conflict handling and the path that reaches standardized port-unavailable reporting.

Suggested labels: NV QA, bug-fix, area: cli, area: onboarding

Suggested reviewers: cv, prekshivyas, ericksoa

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR addresses #6752 by adding fast-fail conflict detection, bounded gateway probes, shared styling, and regression tests.
Out of Scope Changes check ✅ Passed The code changes stay focused on onboarding port-conflict handling, diagnostics, timeouts, and related tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: failing fast when the CLI finds gateway port conflicts.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/6752-onboard-port-conflict

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

@github-code-quality

github-code-quality Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage remains at 96%, unchanged from the branch.

TypeScript / code-coverage/cli

The overall coverage in the branch remains at 79%, unchanged from the branch.

Show a code coverage summary of the most impacted files.
File 3de1de6 86bb9aa +/-
src/lib/core/pr...mpt-activity.ts 92% 67% -25%
src/lib/onboard.ts 29% 28% -1%
src/lib/messagi.../persistence.ts 90% 89% -1%
src/lib/state/m...-acquisition.ts 77% 80% +3%
src/lib/state/gateway.ts 88% 93% +5%
src/lib/actions...ge-preflight.ts 74% 89% +15%
src/lib/onboard...ateway-reuse.ts 0% 45% +45%
src/lib/onboard...ort-conflict.ts 0% 92% +92%
src/lib/onboard...flict-report.ts 0% 100% +100%

Updated July 13, 2026 10:16 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: onboard-repair, onboard-resume, cloud-onboard
Optional E2E: concurrent-gateway-ports

Dispatch hint: onboard-repair,onboard-resume,cloud-onboard

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • onboard-repair: Required deterministic lifecycle-state floor: verify repair still reconciles missing or stale gateway/sandbox state after changed preflight gateway-port classification and reuse behavior.
  • onboard-resume: Required deterministic lifecycle-state floor: verify interrupted onboarding can resume with the revised gateway preflight and bounded reuse probes.
  • cloud-onboard: The shared onboarding preflight runs for hosted onboarding too; validate a complete hosted-inference onboarding flow still creates and uses its gateway successfully.

Optional E2E

  • concurrent-gateway-ports: Adjacent live coverage for two onboarded gateways on distinct ports; it provides confidence that the revised port ownership/reuse logic preserves multi-gateway lifecycle behavior.

New E2E recommendations

  • onboarding (medium): The new CLI integration test proves a mocked foreign listener fails before a mocked OpenShell inspection can hang, but there is no identified dedicated live E2E job that holds a real foreign listener on the configured gateway port and asserts no gateway or sandbox side effects.
    • Suggested test: Add a live onboarding negative-path scenario that occupies NEMOCLAW_GATEWAY_PORT with an unrelated listener, asserts the conflict report and non-zero exit, and verifies gateway and sandbox remain absent.

Dispatch hint

  • Workflow: .github/workflows/e2e.yaml
  • jobs input: onboard-repair,onboard-resume,cloud-onboard

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings

Merge posture: No blocking advisor findings
Primary next action: No advisor follow-up required beyond maintainer review.
Findings: 0 required · 0 warnings · 0 optional suggestions
Since last review: 0 prior items resolved · 0 still apply · 0 new items found

Workflow run details

This is an automated review. Required findings need action before merge. Warnings and optional suggestions do not require a response or follow-up. A human maintainer makes the final merge decision.

@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.

🧹 Nitpick comments (1)
src/lib/onboard.ts (1)

1506-1521: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider threading an injectable exit function for consistency/testability.

failFastOnForeignGatewayPortConflict calls process.exit(1) directly, while the neighboring reconcilePreflightGatewayReuseState call a few lines below uses an injected exitProcess: (code) => process.exit(code). Following the same pattern here would let this new fail-fast/classification logic be covered by a fast unit test instead of relying solely on the CLI-spawning integration test.

♻️ Sketch of DI-friendly signature
-async function failFastOnForeignGatewayPortConflict(): Promise<void> {
-  const portCheck = await checkPortAvailable(
+async function failFastOnForeignGatewayPortConflict(
+  exitProcess: (code: number) => void = (code) => process.exit(code),
+): Promise<void> {
+  const portCheck = await checkPortAvailable(
     GATEWAY_PORT,
     dockerDriverGatewayEnv.getGatewayPortCheckOptions(),
   );
   if (portCheck.ok || couldBeNemoClawGatewayPortListener(portCheck)) return;

   printPortConflictReport({
     port: GATEWAY_PORT,
     label: "OpenShell gateway",
     envVar: "NEMOCLAW_GATEWAY_PORT",
     portCheck,
     serviceHints: getPortConflictServiceHints(),
   });
-  process.exit(1);
+  exitProcess(1);
 }
🤖 Prompt for 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.

In `@src/lib/onboard.ts` around lines 1506 - 1521, Update
failFastOnForeignGatewayPortConflict to accept an injectable exitProcess
callback, defaulting to the existing process.exit behavior, and invoke it with
status 1 instead of calling process.exit directly. Thread the callback from its
callers, matching the exitProcess pattern used by
reconcilePreflightGatewayReuseState, so unit tests can provide a stub without
changing the conflict handling behavior.
🤖 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.

Nitpick comments:
In `@src/lib/onboard.ts`:
- Around line 1506-1521: Update failFastOnForeignGatewayPortConflict to accept
an injectable exitProcess callback, defaulting to the existing process.exit
behavior, and invoke it with status 1 instead of calling process.exit directly.
Thread the callback from its callers, matching the exitProcess pattern used by
reconcilePreflightGatewayReuseState, so unit tests can provide a stub without
changing the conflict handling behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ab21527d-30c1-412b-966c-8b22170962b5

📥 Commits

Reviewing files that changed from the base of the PR and between 3de1de6 and 80eb8be.

📒 Files selected for processing (6)
  • src/lib/onboard.ts
  • src/lib/onboard/gateway-reuse.test.ts
  • src/lib/onboard/gateway-reuse.ts
  • src/lib/onboard/port-conflict-report.test.ts
  • src/lib/onboard/port-conflict-report.ts
  • test/onboard-gateway-port-conflict-fast-fail.test.ts

@sandl99 sandl99 added VDR Linked to VDR finding bug-fix PR fixes a bug or regression v0.0.82 Release target area: cli Command line interface, flags, terminal UX, or output labels Jul 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All selected tests passed

Run: 29246234383
Workflow ref: fix/6752-onboard-port-conflict
Requested targets: onboard-repair,onboard-resume,cloud-onboard
Requested test IDs: (default — all default-enabled tests; explicit-only tests openshell-gateway-auth-contract, mcp-bridge-dev, hermes-gpu-startup, sandbox-rlimits-connect, and jetson-nvmap-gpu are skipped unless selected)
Summary: 3 passed, 0 failed, 0 cancelled, 0 skipped, 0 unknown

Test Result
cloud-onboard ✅ success
onboard-repair ✅ success
onboard-resume ✅ success

@prekshivyas prekshivyas self-assigned this Jul 13, 2026

@prekshivyas prekshivyas 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.

Reviewed current head. Required CI, both PR advisors, CodeRabbit, and all requested onboarding E2E targets are clean. LGTM.

@cv cv merged commit cb807aa into main Jul 13, 2026
137 of 138 checks passed
@cv cv deleted the fix/6752-onboard-port-conflict branch July 13, 2026 18:29
cv pushed a commit that referenced this pull request Jul 14, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Release-prep documentation for v0.0.82 now summarizes user-facing
changes merged since v0.0.81.
It also closes stale wording in the stopped-sandbox backup,
snapshot-clone, Ollama selection, and custom-policy authoring guidance.

## Changes

- Add the `v0.0.82` section to `docs/about/release-notes.mdx` with links
to the focused user guides.
- Document that snapshot clones receive a destination-owned dashboard
port before destructive replacement begins.
- Align `backup-all` guidance with eligible stopped Docker-driver
sandboxes that NemoClaw starts temporarily.
- Describe the running and stopped Ollama menu states without claiming
one fixed label.
- Document runtime rejection of catch-all hosts in custom policy files.

### Source summary

- [#6748](#6748) ->
`docs/about/release-notes.mdx`, `docs/manage-sandboxes/lifecycle.mdx`,
and `docs/reference/commands.mdx`: Summarize non-destructive sandbox
`stop` and `start` commands.
- [#6723](#6723) ->
`docs/about/release-notes.mdx`,
`docs/manage-sandboxes/backup-restore.mdx`, and
`docs/reference/commands.mdx`: Record temporary startup and cleanup for
eligible stopped-sandbox backups.
- [#6749](#6749) ->
`docs/about/release-notes.mdx` and
`docs/manage-sandboxes/backup-restore.mdx`: Document destination-owned
dashboard ports for snapshot clones.
- [#6764](#6764) ->
`docs/about/release-notes.mdx`: Summarize installer handling of
route-only onboarding placeholders.
- [#6771](#6771) ->
`docs/about/release-notes.mdx`, `docs/inference/set-up-vllm.mdx`,
`docs/inference/choose-inference-provider.mdx`,
`docs/reference/commands.mdx`, and
`docs/reference/platform-support.mdx`: Summarize managed-vLLM storage
gates, immutable image digests, and the explicit override boundary.
- [#6759](#6759) ->
`docs/about/release-notes.mdx`: Record early, actionable OpenShell
gateway-port conflict diagnostics.
- [#6753](#6753) ->
`docs/about/release-notes.mdx` and `docs/inference/set-up-ollama.mdx`:
Document truthful running and stopped Ollama menu states.
- [#6776](#6776) ->
`docs/about/release-notes.mdx`: Summarize proxy-independent loopback
readiness checks.
- [#6769](#6769) ->
`docs/about/release-notes.mdx`: Record compatible endpoint and agent
guidance when Chat Completions is unavailable.
- [#6730](#6730) ->
`docs/about/release-notes.mdx`: Summarize bounded reuse of an eligible
successful Chat Completions check.
- [#6768](#6768) ->
`docs/about/release-notes.mdx`: Record route-reservation repair during
resumed onboarding.
- [#6742](#6742) ->
`docs/about/release-notes.mdx`: Summarize pre-mutation resolution of
secret-free sandbox create intent.
- [#6721](#6721) ->
`docs/about/release-notes.mdx` and
`docs/get-started/quickstart-langchain-deepagents-code.mdx`: Record
bounded cleanup of completed managed Deep Agents headless sessions.
- [#6731](#6731) ->
`docs/about/release-notes.mdx` and
`docs/network-policy/customize-network-policy.mdx`: Document runtime
rejection of catch-all custom-policy destinations.
- [#6729](#6729) ->
`docs/about/release-notes.mdx` and `docs/get-started/prerequisites.mdx`:
Record the Node.js 22.19 minimum.
- [#6735](#6735) ->
`docs/about/release-notes.mdx` and
`docs/reference/platform-support.mdx`: Summarize the Ubuntu 26.04
userspace contract without claiming pending host or live validation.
- [#6775](#6775) ->
`docs/about/release-notes.mdx` and
`docs/resources/community-contributions.mdx`: Route independent
solutions outside canonical supported-product documentation.
- [#6740](#6740) ->
`docs/about/release-notes.mdx`: Summarize the semantic
dependency-upgrade contributor workflow.
- [#6777](#6777) ->
`docs/about/release-notes.mdx` and `docs/CONTRIBUTING.md`: Summarize the
route-safe documentation-refactor workflow.
- [#6741](#6741) ->
`docs/about/release-notes.mdx` and
`docs/security/openclaw-2026.6.10-dependency-review.md`: Summarize
reviewed npm archive verification and audit enforcement.
- [#6739](#6739) ->
`docs/about/release-notes.mdx` and
`docs/security/openclaw-2026.6.10-dependency-review.md`: Record the
locked offline dependency graph for the managed OpenClaw WeChat runtime.
- [#6737](#6737) ->
`docs/about/release-notes.mdx`: Record removal of the messaging build
plan from final OpenClaw and Hermes image environments.
- [#6733](#6733) ->
`docs/about/release-notes.mdx`: Summarize cached plugin dependency
layers for source and blueprint rebuilds.

### Skipped from docs-skip

- None. No commit or changed path in `v0.0.81..origin/main` matched
`openclaw-sandbox-permissive.yaml` or `config-show`, and the drafted
content contains none of the configured skip terms.

## 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 is a documentation-only
release-prep update; behavior is protected by the merged source PRs, and
the documentation build validates the changed routes and agent variants.
- [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:

## Verification

- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — tests are not applicable for this
documentation-only change.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result: not run for this
documentation-only change.
- [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) — 0
errors; two pre-existing Fern warnings remain.
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)
— no new pages.

---
Signed-off-by: Charan Jagwani <cjagwani@nvidia.com>


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

## Summary by CodeRabbit

* **Documentation**
* Updated release notes with improvements to sandbox recovery,
onboarding, session management, policy validation, storage checks, and
system requirements.
  * Clarified Ollama setup instructions and status labels.
* Documented safer snapshot restoration, including dedicated ports and
protection against destructive failures.
* Expanded `backup-all` coverage to include eligible stopped sandboxes.
* Added guidance rejecting broad or catch-all network destinations in
custom policies.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Charan Jagwani <cjagwani@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: cli Command line interface, flags, terminal UX, or output bug-fix PR fixes a bug or regression v0.0.82 Release target VDR Linked to VDR finding

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[DGX Station][All platforms] Port 8080 conflict can stall onboarding and lacks warning contrast

3 participants