Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/reference/troubleshooting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ It rejects remote endpoints and relative socket paths before service startup.

The `invalid_docker_host` advisory means that `DOCKER_HOST` is not an absolute local `unix://` socket path that NemoClaw can write to the managed OpenShell gateway service environment.
NemoClaw does not use the standalone gateway fallback when this validation fails.
Onboarding prints the advisory identifier in parentheses after each action title in the `Suggested fix` list.
The terminal output names `invalid_docker_host` when this validation fails, so you can match the message to this section.
Remove the override to use Docker's default local socket:

```bash
Expand Down
30 changes: 29 additions & 1 deletion src/lib/onboard/preflight-docker-host.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,43 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import { describe, expect, it } from "vitest";
import { afterEach, describe, expect, it, vi } from "vitest";

import { assessHost, planHostRemediation } from "./preflight";
import { printRemediationActions } from "./remediation";

// Regression: NemoClaw #7731. This invalid TCP endpoint makes `docker info`
// fail, but the local docker.service is still active. Preflight used to emit
// the docker-group remediation. The host assessment now flags the invalid
// DOCKER_HOST so onboarding names it instead.
describe("assessHost invalid DOCKER_HOST (#7731)", () => {
describe("printRemediationActions", () => {
afterEach(() => {
vi.restoreAllMocks();
});

it("prints the advisory identifier after the remediation title", () => {
const assessment = assessHost({
platform: "linux",
env: { DOCKER_HOST: "tcp://203.0.113.10:2375" },
dockerInfoOutput: "",
commandExistsImpl: (name: string) => name === "docker" || name === "systemctl",
runCaptureImpl: (command: readonly string[]) =>
command.includes("is-active") ? "active" : "",
});

const err = vi.spyOn(console, "error").mockImplementation(() => undefined);
printRemediationActions(planHostRemediation(assessment));
const output = err.mock.calls.map((call: unknown[]) => String(call[0])).join("\n");

expect(output).toContain("Fix the DOCKER_HOST endpoint (invalid_docker_host):");
expect(output).toContain("unset DOCKER_HOST");
expect(output).toContain("unix:///var/run/docker.sock");
expect(output).not.toContain("docker_group_permission");
expect(output).not.toContain("start_docker");
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
});

it("flags an invalid DOCKER_HOST so onboarding names the endpoint, not a docker-group fix", () => {
const assessment = assessHost({
platform: "linux",
Expand Down
7 changes: 5 additions & 2 deletions src/lib/onboard/remediation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import path from "node:path";
const OPENCLAW_LAUNCH_AGENT_PLIST = "~/Library/LaunchAgents/ai.openclaw.gateway.plist";

export function printRemediationActions(
actions: Array<{ title: string; reason: string; commands?: string[] }> | null | undefined,
actions:
| Array<{ id: string; title: string; reason: string; commands?: string[] }>
| null
| undefined,
): void {
if (!Array.isArray(actions) || actions.length === 0) {
return;
Expand All @@ -16,7 +19,7 @@ export function printRemediationActions(
console.error(" Suggested fix:");
console.error("");
for (const action of actions) {
console.error(` - ${action.title}: ${action.reason}`);
console.error(` - ${action.title} (${action.id}): ${action.reason}`);
for (const command of action.commands || []) {
console.error(` ${command}`);
}
Expand Down
Loading