Skip to content

fix(onboard): detect unreachable Docker daemon in preflight (#2348) - #2372

Merged
cv merged 2 commits into
mainfrom
fix/2348-docker-preflight-colima-false-positive
May 23, 2026
Merged

fix(onboard): detect unreachable Docker daemon in preflight (#2348)#2372
cv merged 2 commits into
mainfrom
fix/2348-docker-preflight-colima-false-positive

Conversation

@chengjiew

@chengjiew chengjiew commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Root cause: docker info --format '{{json .}}' exits 0 and emits a zero-value client-side struct ("ServerVersion":"" plus a populated ServerErrors array) when the Docker daemon is unreachable — e.g. after colima stop. The prior preflight check only looked at whether stdout was non-empty, so it misread that struct as "daemon running".
  • Replaced the check with isDockerDaemonReachable, a layered JSON-based helper (see below).
  • Result: [1/8] Preflight checks now reports Docker as unreachable with an actionable remediation (start_docker), instead of passing and then hanging at [2/8] with a cryptic Socket not found: /var/run/docker.sock.

Detection logic

Signal Meaning
ServerErrors is a non-empty array Unreachable — explicit negative signal from docker CLI
ServerVersion is a non-empty string Reachable — canonical for docker CLI and podman's docker-compat socket (confirmed via podman source)
version.Version is a non-empty string Reachable — podman-docker alias native schema
Output is not valid JSON Reachable — older CLI / test-injection fallback, matches prior heuristic
Otherwise Unreachable — conservative default

Test plan

  • Added regression test for Colima-stopped JSON (ServerVersion: "" + ServerErrors set) — reproduces [NemoClaw][macOS][Onboard] Preflight check [1/8] falsely reports "✓ Docker is running" when Colima daemon is stopped #2348 without a mac host
  • Added tests for: zero-value JSON without ServerErrors, non-object JSON ("null"), non-JSON fallback, and podman-docker-alias native output
  • Updated two existing podman tests that had used unrealistic plain-text dockerInfoOutput to realistic JSON payloads
  • npx vitest run src/lib/preflight.test.ts → 41/41 passing locally
  • Verified end-to-end by running the new helper against the real failure output captured from DOCKER_HOST=unix:///tmp/nonexistent.sock docker info --format '{{json .}}' (daemon-down → unreachable, daemon-up → reachable)

Fixes #2348

Signed-off-by: Chengjie Wang chengjiew@nvidia.com

🤖 Generated with Claude Code

Summary by CodeRabbit

Tests

  • Added comprehensive test coverage for Docker/Podman daemon reachability detection across multiple scenarios.

Bug Fixes

  • Improved Docker/Podman availability detection to more accurately determine daemon status through enhanced JSON parsing and error handling.

`docker info --format '{{json .}}'` exits 0 and emits a zero-value
client-side struct (ServerVersion: "", populated ServerErrors) when the
daemon is unreachable — e.g. after `colima stop`. The prior
non-empty-output check treated that as "daemon running", so preflight
passed and onboarding failed on the next step with a cryptic socket
error.

Replace the check with isDockerDaemonReachable, which parses the JSON
and uses layered signals:
- ServerErrors non-empty → unreachable (explicit negative)
- ServerVersion populated → reachable (canonical docker / podman-compat)
- version.Version populated → reachable (podman-docker alias native)
- non-JSON output → fall back to non-empty heuristic

Fixes #2348

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The PR enhances the Docker daemon reachability check by replacing a simple "non-empty output" heuristic with JSON-aware parsing that examines ServerErrors and ServerVersion fields in docker info output, while maintaining backward compatibility with non-JSON responses.

Changes

Cohort / File(s) Summary
Daemon Reachability Detection
src/lib/preflight.ts
Adds new isDockerDaemonReachable function that parses JSON from docker info --format '{{json .}}', returns false if ServerErrors is present/non-empty, returns true if ServerVersion or podman's version.Version is non-empty, and falls back to checking non-empty output for backward compatibility with non-JSON responses.
Test Coverage
src/lib/preflight.test.ts
Updates podman-on-macOS and podman-on-Linux test inputs to use JSON-formatted dockerInfoOutput. Adds regression tests validating zero-value JSON with ServerErrors is unreachable, invalid JSON is unreachable, non-JSON plain-text preserves backward compatibility as reachable, and native podman JSON output is recognized as reachable.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A JSON parse with care so true,
No more false reports of "daemon's through!"
ServerErrors caught, ServerVersion blessed,
Our preflight checks now know the best! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(onboard): detect unreachable Docker daemon in preflight (#2348)' directly and clearly summarizes the main change: improving Docker daemon reachability detection in the preflight check to fix a false positive when Colima is stopped.
Linked Issues check ✅ Passed The PR fully addresses all coding requirements from issue #2348: implements JSON-aware daemon reachability detection using ServerErrors/ServerVersion/version.Version fields, treats zero-value JSON as unreachable, preserves backward compatibility with non-JSON output, and includes comprehensive regression test coverage [#2348].
Out of Scope Changes check ✅ Passed All changes are tightly scoped to the stated objective: additions to src/lib/preflight.ts implement the isDockerDaemonReachable helper function, and src/lib/preflight.test.ts adds regression tests with realistic JSON test cases. No unrelated modifications are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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/2348-docker-preflight-colima-false-positive

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

@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/preflight.ts (1)

206-210: Tighten the non-JSON fallback to avoid plain-text false positives.

At Line 209, any non-JSON non-empty output is treated as reachable. If the output is a plain-text daemon-connect error, this can still misclassify unreachable Docker as reachable.

Suggested hardening
   try {
     parsed = JSON.parse(text);
   } catch {
-    // Output fell outside the `--format '{{json .}}'` contract (older CLI,
-    // stubbed test input, etc.). The CLI at least produced something, so
-    // defer to the prior non-empty heuristic for backward compatibility.
-    return true;
+    // Backward-compatible fallback for non-JSON output, but avoid
+    // known daemon-connect error false positives.
+    const lowered = text.toLowerCase();
+    if (
+      lowered.includes("cannot connect to the docker daemon") ||
+      lowered.includes("error during connect")
+    ) {
+      return false;
+    }
+    return true;
   }

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e18e9543-a56f-49ce-8bab-c1dc56629ff1

📥 Commits

Reviewing files that changed from the base of the PR and between 6b413f5 and 3380f1f.

📒 Files selected for processing (2)
  • src/lib/preflight.test.ts
  • src/lib/preflight.ts

@wscurran

Copy link
Copy Markdown
Contributor

✨ Thanks for submitting this pull request that proposes a way to fix a bug that causes the onboard session to hang when the Docker daemon is unreachable.


Related open issues:

@github-actions

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: cloud-onboard-e2e, onboard-negative-paths-e2e, ubuntu-no-docker-preflight-negative
Optional E2E: macos-e2e, wsl-e2e, gpu-repo-local-ollama-openclaw

Dispatch hint: cloud-onboard-e2e,onboard-negative-paths-e2e

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: medium

Required E2E

  • cloud-onboard-e2e (medium): Exercises install plus non-interactive cloud onboarding on a real Docker host. Required to verify the stricter Docker daemon reachability check still allows the normal Docker-running path and reaches a usable sandbox/inference setup.
  • onboard-negative-paths-e2e (medium): Covers onboarding validation and negative/edge paths around Docker availability, invalid credentials, port conflicts, and live non-interactive onboard behavior. This is the closest existing regression-style E2E for preflight/onboard failure handling.
  • ubuntu-no-docker-preflight-negative (medium): Scenario-runner coverage for preflight failure before sandbox creation when Docker is unavailable. Required because the changed assessHost logic directly determines Docker reachability and should continue to fail closed for unavailable runtimes.

Optional E2E

  • macos-e2e (medium): The motivating regression is macOS/Colima stopped-daemon behavior. Existing macOS E2E is useful platform confidence, though GitHub-hosted macOS may skip Docker-dependent coverage when Docker is unavailable.
  • wsl-e2e (high): assessHost contains nearby WSL/Docker runtime branching. Optional confidence that Docker-running onboarding still works in WSL after the daemon-reachability parser change.
  • gpu-repo-local-ollama-openclaw (high): Optional adjacent coverage for local Ollama onboarding and Docker/CDI runtime parsing, especially because test/onboard-selection.test.ts touched Ollama validation harness behavior.

New E2E recommendations

  • onboarding/preflight Docker stopped-daemon regression (high): No existing E2E appears to assert the exact [NemoClaw][macOS][Onboard] Preflight check [1/8] falsely reports "✓ Docker is running" when Colima daemon is stopped #2348 shape: docker CLI installed, docker info --format exits successfully, but emits zero-value JSON with empty ServerVersion and ServerErrors after a stopped daemon such as colima stop. Unit tests cover it, but an E2E/regression guard would prevent reintroducing the false-positive onboard path.
    • Suggested test: Add a regression E2E that injects or shims docker info --format '{{json .}}' to return zero-value JSON with ServerErrors, runs nemoclaw onboard/preflight, and asserts onboarding fails before sandbox creation with actionable Docker-daemon-not-running remediation.
  • podman-docker compatibility (medium): The new parser treats native podman JSON as reachable via version.Version. Existing coverage found here is unit-level; an E2E would be useful if podman-docker alias support is intended as a real supported environment.
    • Suggested test: Add a lightweight preflight regression E2E with a docker shim returning podman-native info JSON and assert assess/onboard reports a reachable but unsupported podman runtime consistently.

Dispatch hint

  • Workflow: nightly-e2e.yaml
  • jobs input: cloud-onboard-e2e,onboard-negative-paths-e2e

@github-actions

Copy link
Copy Markdown
Contributor

E2E Scenario Advisor Recommendation

Required scenario E2E: None
Optional scenario E2E: None

Workflow run

Full scenario advisor summary

E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required scenario E2E

  • None. No scenario workflow, scenario metadata, scenario runtime, or validation-suite files changed.

Optional scenario E2E

  • None.

Relevant changed files

  • None.

@github-actions

Copy link
Copy Markdown
Contributor

PR Review Advisor

Findings: 2 needs attention, 1 worth checking, 0 nice ideas
Top item: Large preflight monolith grew further

Review findings

🛠️ Needs attention

  • Large preflight implementation grew further (src/lib/onboard/preflight.ts:213): The PR adds the Docker reachability helper directly to src/lib/onboard/preflight.ts, increasing an already large file from 1382 to 1438 lines (+56). This file is an active preflight hotspot with substantial recent churn, so further growth increases review and maintenance risk in sandbox/onboarding lifecycle logic.
    • Recommendation: Extract the Docker info reachability parser into a focused helper/module, or otherwise offset the growth by moving related parsing/preflight code out of this monolith before merge.
    • Evidence: Deterministic monolith check: src/lib/onboard/preflight.ts baseLines=1382, headLines=1438, delta=56, severity=blocker. Drift evidence shows recent active preflight work in this same file.
  • Large preflight test monolith grew further (src/lib/onboard/preflight.test.ts:333): The PR adds 106 lines of regression tests to an already very large preflight test file, growing it from 1564 to 1670 lines. The added cases are useful, but continuing to expand the monolithic test file makes future preflight changes harder to isolate and review.
    • Recommendation: Move the Docker daemon reachability cases into a focused test module or split the existing assessHost Docker-runtime tests so this growth is offset before merge.
    • Evidence: Deterministic monolith check: src/lib/onboard/preflight.test.ts baseLines=1564, headLines=1670, delta=106, severity=blocker.

🔎 Worth checking

  • Runtime validation still recommended for Docker daemon reachability (src/lib/onboard/preflight.ts:517): The new unit tests cover the JSON shapes and plain-text fallback behavior, but the changed path is infrastructure-facing preflight logic that depends on real Docker/Colima CLI behavior. The linked bug is specifically a macOS Colima stopped-daemon scenario, and the diff does not add a targeted runtime/integration validation artifact for that behavior.
    • Recommendation: Add or identify targeted runtime/integration validation for the changed Docker/Colima preflight behavior, without relying on external E2E status as the only evidence.
    • Evidence: Trusted test-depth signal: verdict=runtime_validation_recommended for src/lib/onboard/preflight.ts. Added tests simulate Colima-stopped JSON and related cases in src/lib/onboard/preflight.test.ts, but do not exercise a real Docker/Colima daemon boundary.

🌱 Nice ideas

  • None.

Workflow run details

This is an automated advisory review. A human maintainer must make the final merge decision.

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

Approved after maintainer salvage. Rebased/merged onto current main, moved the Docker daemon reachability fix onto the current onboard preflight module, added regression coverage for zero-value Docker JSON and plain-text daemon errors, and made the local test suite hermetic against host Git signing config and real Ollama auth-proxy spawns. Local validation: make check, npm test, npm run typecheck:cli. CI is green.

@cv
cv merged commit 6b20e38 into main May 23, 2026
26 checks passed
@wscurran wscurran added area: packaging Packages, images, registries, installers, or distribution platform: container Affects Docker, containerd, Podman, or images and removed area: packaging Packages, images, registries, installers, or distribution Docker labels Jun 3, 2026
@wscurran wscurran added the bug-fix PR fixes a bug or regression label Jun 8, 2026
@wscurran wscurran added the NV QA Bugs found by the NVIDIA QA Team label Jun 26, 2026
@cv
cv deleted the fix/2348-docker-preflight-colima-false-positive branch June 28, 2026 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug-fix PR fixes a bug or regression NV QA Bugs found by the NVIDIA QA Team platform: container Affects Docker, containerd, Podman, or images

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[NemoClaw][macOS][Onboard] Preflight check [1/8] falsely reports "✓ Docker is running" when Colima daemon is stopped

3 participants