NVIDIA / NVIDIA/NemoClaw

Onboarding preflight runs docker info without a timeout, so a hung daemon hangs onboard silently

Open
#10,645 1 comment 0 reactions 0 assignees View on GitHub
area: install area: onboarding
Dominant language
TypeScript
Stars
22.5k
Forks
3.1k
Avg merge
1d 1h
Merged PRs (30d)
715

Description

## Description

Onboarding's Docker preflight runs `docker info` with no timeout, so a Docker authority that accepts the connection but never answers hangs `nemoclaw onboard` indefinitely, with no diagnostic and no recovery action.

```ts
// src/lib/onboard/preflight.ts:569-572
dockerInfoOutput = runCaptureImpl(["docker", "info", "--format", "{{json .}}"], {
ignoreError: true,
});
```

`runCapture` forwards its options straight to `spawnSync` and adds no timeout of its own (`src/lib/runner.ts:296-322`), so nothing bounds this call. A hung daemon or a `DOCKER_HOST` pointing at a socket that accepts and stalls produces a silent, unbounded wait at step 1 of onboarding, before any resource is created.

Detection is already bounded for comparison: `probeDockerHost` caps every probe at `DOCKER_PROBE_TIMEOUT_MS` = 3 seconds (`src/lib/platform.ts`). Preflight then re-asks the same question with no bound at all.

## Expected behavior

The preflight Docker call is bounded. On expiry the operator is told that the configured Docker authority did not answer within the bound, which authority was used when it is known, and what to do next — retry, correct `DOCKER_HOST`, or repair Docker. A timeout should be distinguishable from an ordinary "not reachable" result rather than collapsed into it.

## Scope note

This is pre-existing and independent of any recent change: the call above is byte-identical on `main` and on the head of #10379.

It is worth recording now because #10379 makes the path easier to reach. Before that change, an ambient probe that timed out was treated as a refusal, so detection could redirect to a discovered socket and preflight would then query that socket instead — fast, but pointed at a runtime the host never chose, which is the defect #10367 reports. After it, an inconclusive probe correctly keeps the host default, so a genuinely hung default now stays the authority preflight queries. The correct authority is the right outcome; the missing bound is what turns it into a silent hang.

## Suggested shape

1. Give the preflight Docker calls an explicit timeout, in the same range as the detection probe rather than the multi-minute default used for long operations.
2. Keep the timeout distinct in the result so the message can name it, instead of `ignoreError: true` flattening it to an empty string.
3. Cover it with a test where the Docker command exceeds the bound and preflight reports the timeout-specific diagnostic without starting onboarding.

## Notes

Surfaced by the PR Review Advisor on #10379. Related: #10367, #10622, #10632.

Contributor guide

Open the contributing guide

Research direction

Start in src/lib/onboard/preflight.ts at lines 569-572 and compare the bounded probe in src/lib/platform.ts with option forwarding in src/lib/runner.ts lines 296-322. Trace how preflight handles the Docker command result, then add coverage for a command exceeding the bound. Done means a hung Docker authority produces a distinct timeout diagnostic with the known authority and recovery guidance without starting onboarding.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, typescript
Domain
cli, devops
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.