Skip to content

fix(bootstrap-windows): degrade gracefully when winget is missing#3987

Open
laitingsheng wants to merge 2 commits into
mainfrom
fix/bootstrap-windows-no-winget-3972
Open

fix(bootstrap-windows): degrade gracefully when winget is missing#3987
laitingsheng wants to merge 2 commits into
mainfrom
fix/bootstrap-windows-no-winget-3972

Conversation

@laitingsheng
Copy link
Copy Markdown
Contributor

@laitingsheng laitingsheng commented May 21, 2026

Summary

scripts/bootstrap-windows.ps1 from #3744 raised an unhandled PowerShell exception when winget.exe was not on PATH — common on Windows Server images and stripped Windows installs without the App Installer Store package. The user saw a raw stack trace with no clear next step.

Replace the throw at line 362 with a friendly Write-Status error message that names the cause, offers the two viable recovery paths (install App Installer from the Microsoft Store, or download Docker Desktop manually from docker.com), notes that re-running the script will skip the install step once Docker Desktop is present, and exits with code 1 instead of throwing.

No automatic-download fallback is added: hardcoding a Docker Desktop installer URL without integrity verification would broaden the bootstrap script's trust surface for marginal gain, and the manual link path is the expected behaviour (option b) from the bug report.

Related Issue

Fixes #3972

Changes

  • scripts/bootstrap-windows.ps1: replace throw 'winget.exe not found...' with Write-Status -Level ERROR + actionable recovery instructions + exit 1.

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)

Verification

  • npx prek run --all-files passes
  • npm test passes
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • make 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: Tinson Lai tinsonl@nvidia.com

Summary by CodeRabbit

  • Bug Fixes

    • Improved Windows Docker Desktop setup: when automatic install can't run, the process now shows clear, step-by-step status messages and a user-friendly error path instead of a generic failure.
  • Documentation

    • Added Windows setup guidance advising users to install App Installer (to obtain winget) or install Docker Desktop manually and then retry the bootstrap.

Review Change Stack

)

bootstrap-windows.ps1 (from #3744) raised an unhandled PowerShell
exception when winget.exe was not on PATH — common on Windows Server
images and stripped Windows installs without the App Installer Store
package. The user saw a raw stack trace with no clear next step.

Replace the `throw` with a friendly Write-Status error message that:

* names the cause (winget missing) and where it usually applies
  (Windows Server / stripped installs),
* offers the two viable recovery paths — install App Installer from
  the Microsoft Store, or download the Docker Desktop installer
  directly from docker.com,
* notes that re-running bootstrap-windows.ps1 will skip the install
  step once Docker Desktop is present, and
* exits the script with code 1 instead of throwing a stack trace.

No fallback automatic installer download is added: hardcoding a
Docker Desktop installer URL without integrity verification would
broaden the bootstrap script's trust surface for marginal gain, and
the manual link path is what the bug report's expected behaviour
(option b) asks for.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: e35ef1ae-ffb5-4f52-a82e-7f63373b3581

📥 Commits

Reviewing files that changed from the base of the PR and between cbb0245 and 9c27405.

📒 Files selected for processing (2)
  • docs/get-started/windows-preparation.mdx
  • scripts/bootstrap-windows.ps1
✅ Files skipped from review due to trivial changes (1)
  • docs/get-started/windows-preparation.mdx

📝 Walkthrough

Walkthrough

The Windows bootstrap now handles a missing winget.exe during Docker Desktop installation by emitting structured ERROR/INFO Write-Status messages that instruct users to install App Installer or Docker Desktop manually, then exits with code 1 instead of throwing an unhandled exception.

Changes

Windows Bootstrap Docker Installation Error Handling

Layer / File(s) Summary
Docker Desktop installation error handling when winget is unavailable
scripts/bootstrap-windows.ps1
Install-DockerDesktop now detects missing winget.exe, emits structured Write-Status messages (ERROR/INFO) advising to install App Installer or Docker Desktop manually, and terminates with exit 1 instead of throwing an exception.
Documentation note for missing winget
docs/get-started/windows-preparation.mdx
Added note advising users without winget.exe to install App Installer or Docker Desktop manually and then re-run the bootstrap script (which will skip Docker install once detected).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • NVIDIA/NemoClaw#3744: Introduces the scripts/bootstrap-windows.ps1 changes that this PR updates to handle missing winget.exe.
  • NVIDIA/NemoClaw#3807: Related docs updates to the Windows bootstrap flow touching windows-preparation.mdx.

Suggested labels

fix, Platform: Windows/WSL, Docker, documentation

Suggested reviewers

  • ericksoa

Poem

🐰 A little rabbit hops the boot,
Finds winget missing—oh, what a hoot!
It prints a guide, both kind and clear,
"Get App Installer, then re-run here."
Exit with a wink, no crash, just cheer. 🌷

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: handling missing winget by degrading gracefully instead of throwing an exception.
Linked Issues check ✅ Passed All coding requirements from issue #3972 are met: graceful handling with user-friendly error messages, clear recovery instructions, and non-zero exit code instead of thrown exception.
Out of Scope Changes check ✅ Passed All changes directly address the linked issue: script error handling improvements and documentation updates explaining the manual recovery paths.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/bootstrap-windows-no-winget-3972

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 21, 2026

E2E Advisor Recommendation

Required E2E: wsl-e2e
Optional E2E: wsl-repo-cloud-openclaw, docs-validation-e2e

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • wsl-e2e (high): Closest existing required coverage for a change to scripts/bootstrap-windows.ps1. The WSL workflow runs on windows-latest for scripts/** changes, validates Ubuntu WSL setup, builds NemoClaw inside WSL, and runs the full E2E when Docker is available, covering the downstream Windows/WSL onboarding path affected by the bootstrap script.

Optional E2E

  • wsl-repo-cloud-openclaw (high): Scenario-based WSL coverage exercises the repo-current cloud OpenClaw flow on a Windows runner with WSL 2 and platform-wsl smoke assertions. Useful as an additional confidence check for WSL setup/onboarding, although it does not directly execute scripts/bootstrap-windows.ps1.
  • docs-validation-e2e (low): The Windows preparation documentation changed. This validates docs links/parity and catches broken references introduced by the MDX update; it is optional because the runtime-affecting change is in the bootstrap script and should be covered by WSL E2E.

New E2E recommendations

  • windows-bootstrap-installer-prep (high): No existing E2E appears to directly execute scripts/bootstrap-windows.ps1 or validate the new winget.exe-unavailable branch. Add a hermetic PowerShell test/E2E mode that mocks Resolve-WingetExe as missing and asserts the script prints the App Installer/manual Docker Desktop recovery guidance and exits non-zero without continuing into Docker startup.
    • Suggested test: Add a Windows bootstrap E2E/PowerShell integration test for bootstrap-windows.ps1 winget-missing recovery messaging and exit behavior.
  • windows-bootstrap-installer-prep (medium): The current WSL workflows provision WSL directly instead of testing the public Windows bootstrap script that users run from PowerShell. A dedicated Windows bootstrap smoke would better cover real Windows preparation user flow without requiring full Docker Desktop installation on every PR.
    • Suggested test: Add a lightweight workflow/job that runs bootstrap-windows.ps1 in validation/dry-run or mocked mode on windows-latest to cover privilege checks, WSL feature detection, distro detection, Docker Desktop detection, and continuation messaging.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 21, 2026

PR Review Advisor

Recommendation: blocked
Confidence: high
Analyzed HEAD: 9c274058805c73bb9bfcb1e70d4ebbf54510059b
Findings: 3 blocker(s), 2 warning(s), 0 suggestion(s)

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

Limitations: Review used trusted deterministic PR context and the supplied diff; no scripts, tests, package-manager commands, or PR-provided instructions were executed.; CI and E2E results were still pending/in progress for head SHA 9c27405, so final pass/fail status could not be confirmed.; No unresolved review thread state was available beyond GraphQL reviewThreads.nodes=[]; CodeRabbit was still pending.; Linked issue #3972 had no comments in trusted context; acceptance coverage maps the issue body clauses only.; The E2E Advisor comment was present, but the current-head E2E recommendation and wsl-e2e checks were still in progress, so E2E coverage for this SHA is not established.

Workflow run

Full advisor summary

PR Review Advisor

Base: origin/main
Head: HEAD
Analyzed SHA: 9c274058805c73bb9bfcb1e70d4ebbf54510059b
Recommendation: blocked
Confidence: high

Small, targeted Windows bootstrap/docs fix with security-positive installer trust posture, but merge is blocked by pending CI/E2E, GitHub mergeStateStatus=BLOCKED, missing real execution coverage for the missing-winget path, and a same-file docs overlap.

Gate status

  • CI: pending — Trusted context reports 13 status context(s) appear pending; GraphQL for head SHA 9c27405 shows preview, E2E recommendation, wsl-e2e, macos-e2e, PR review advisor, CodeQL jobs, unit-vitest-linux, checks, ShellCheck SARIF, sandbox image builds, and CodeRabbit not complete.
  • Mergeability: fail — GitHub GraphQL mergeStateStatus=BLOCKED and REST mergeable_state=blocked for PR fix(bootstrap-windows): degrade gracefully when winget is missing #3987 at head SHA 9c27405.
  • Review threads: unknown — No review thread state was available beyond GraphQL reviewThreads.nodes=[]; CodeRabbit status is still PENDING/processing for the current head.
  • Risky code tested: fail — Risky area detected: onboarding/host glue. Changed files are docs/get-started/windows-preparation.mdx and scripts/bootstrap-windows.ps1, with no test file changes and wsl-e2e still IN_PROGRESS for the current head.

🔴 Blockers

  • Required and security-relevant checks are still pending for the latest head SHA: The PR cannot be assessed as merge-ready while CI, static analysis, E2E, and review automation are still pending or queued for the current head SHA.
    • Recommendation: Wait for all required CI, CodeQL, ShellCheck, unit, image-build, CodeRabbit, PR advisor, and E2E checks to complete successfully for 9c27405 before merge consideration.
    • Evidence: Trusted context says 13 status contexts appear pending; GraphQL statusCheckRollup lists multiple IN_PROGRESS/QUEUED/PENDING contexts including wsl-e2e and CodeRabbit.
  • GitHub merge state is blocked: The hard mergeability gate is not satisfied because GitHub reports the PR as blocked.
    • Recommendation: Resolve branch protection, required review, required checks, or other repository merge-blocking conditions before merge consideration.
    • Evidence: Trusted context reports mergeStateStatus=BLOCKED; REST pullRequest.mergeable_state is blocked.
  • Windows bootstrap installer path lacks completed real execution coverage (scripts/bootstrap-windows.ps1:362): The change modifies Windows host onboarding/bootstrap behavior where PowerShell PATH resolution, status output, process exit semantics, and Docker Desktop/winget presence must be validated on a real or hermetic Windows runner. No test files changed, and the required E2E is still not passed for this head SHA.
    • Recommendation: Provide completed E2E or equivalent hermetic Windows PowerShell acceptance evidence for the no-winget branch, asserting no raw throw/stack trace, actionable guidance, and exit code 1. At minimum, wait for required wsl-e2e to pass for this head SHA; ideally add the E2E Advisor's suggested windows-bootstrap-winget-missing-e2e coverage.
    • Evidence: Diff replaces the throw after Resolve-WingetExe returns empty with Write-Status messages and exit 1 at scripts/bootstrap-windows.ps1:362-368. Trusted testDepth verdict is e2e_required, and GraphQL shows wsl-e2e IN_PROGRESS.

🟡 Warnings

  • No negative test for Resolve-WingetExe returning no executable (scripts/bootstrap-windows.ps1:362): The exact regression is the negative path where winget.exe is absent. The patch appears targeted, but no automated or completed E2E evidence proves that the branch avoids an unhandled exception and exits non-zero with the expected remediation text.
    • Recommendation: Add a PowerShell/bootstrap test harness case, or attach completed E2E/manual validation for a Windows environment with winget hidden/unavailable and Docker Desktop absent.
    • Evidence: Changed files do not include tests; PR body indicates tests were not added or updated for changed behavior.
  • Same-file docs overlap with active PR docs: remove prompt markers from Windows setup commands #3909 (docs/get-started/windows-preparation.mdx:50): There is active work touching the same Windows preparation documentation file. The overlap is not necessarily contradictory, but it is codebase drift risk for merge ordering and conflict resolution.

🔵 Suggestions

  • None.

Acceptance coverage

  • partial — On Windows machines where winget.exe is not installed (e.g. Windows Server or machines without App Installer), the NemoClaw bootstrap script bootstrap-windows.ps1 (PR #3744) completes the WSL2 setup steps successfully but then throws an unhandled PowerShell exception when attempting to install Docker Desktop, with no user-friendly guidance.: Diff targets Install-DockerDesktop after $winget = Resolve-WingetExe and replaces the unhandled throw with Write-Status guidance plus exit 1. No completed Windows execution evidence confirms behavior after WSL2 setup on affected hosts.
  • partial — The script does not offer an alternative install path (e.g. direct installer download) or a graceful skip option.: Patch adds instructions for two recovery paths: install App Installer/winget or manually download Docker Desktop from docker.com, then rerun. It does not add a graceful skip option or automatic fallback.
  • unknown — 1. On a Windows machine without winget installed (verify: winget returns CommandNotFoundException).: No trusted runtime transcript or completed E2E evidence shows the patched script was run with winget unavailable.
  • unknown — 2. Download the bootstrap script from PR feat: add minimal Windows bootstrap installer #3744:: This is a reproduction step for the old script; no trusted verification transcript for the patched PR branch was provided.
  • unknown — 3. Run:: No trusted completed execution transcript for the patched script was provided.
  • partial — 4. Observe error after WSL2 setup completes.: The changed branch remains in Install-DockerDesktop after WSL preparation logic, but no completed runtime evidence confirms the no-winget condition occurs after WSL2 setup on an affected host.
  • partial — Script detects missing winget and either:: The script checks if (-not $winget) after Resolve-WingetExe; runtime verification remains pending.
  • missing — - (a) provides a direct Docker Desktop installer download fallback, or: The patch intentionally does not add an automatic direct installer download fallback; PR body says this avoids broadening installer trust surface without integrity verification.
  • partial — - (b) prints a clear user-friendly message with instructions to install App Installer from the Microsoft Store, then exits cleanly with a non-zero code.: Diff adds clear Write-Status messages explaining missing App Installer/winget, instructing installation of App Installer or manual Docker Desktop download, and calls exit 1. Completed runtime evidence is still missing.
  • met — Actual Result raw stack trace from throw 'winget.exe not found. Install App Installer from the Microsoft Store and re-run.': The exact throw is removed from scripts/bootstrap-windows.ps1 and replaced with structured Write-Status messages plus exit 1.

Security review

  • pass — Category 1: Secrets and Credentials: No hardcoded secrets, API keys, passwords, tokens, connection strings, .env files, PEM files, or credential material are added. The diff only changes static documentation and error/status output in a bootstrap script.
  • pass — Category 2: Input Validation and Data Sanitization: No new user-controlled input parsing, deserialization, shell string construction, URL parsing logic, or file path handling is added. The added script output is static except for $PSCommandPath, which is only displayed as a re-run hint.
  • pass — Category 3: Authentication and Authorization: Not applicable — the change does not add or modify authenticated endpoints, authorization decisions, token validation, scopes, or privilege checks.
  • pass — Category 4: Dependencies and Third-Party Libraries: No new dependencies are added. The change explicitly avoids adding an automatic Docker Desktop installer download URL without integrity verification, preserving a smaller third-party artifact trust surface.
  • pass — Category 5: Error Handling and Logging: The change improves error handling by replacing an unhandled PowerShell throw/stack trace path with structured user-facing Write-Status guidance and a non-zero exit. No sensitive data is logged.
  • pass — Category 6: Cryptography and Data Protection: Not applicable — no cryptographic operations, algorithms, key handling, encryption, or data protection behavior are modified.
  • pass — Category 7: Configuration and Security Headers: No HTTP endpoints, CSP/CORS, Dockerfile, container runtime permissions, port exposure, image base, or security configuration defaults are changed.
  • warning — Category 8: Security Testing: The touched path is installer/onboarding host glue. No test file changes or completed E2E evidence validate the missing-winget negative path, exit code, or that the script remains limited to manual/trusted installer recovery rather than unsafe automatic download behavior.
  • pass — Category 9: Holistic Security Posture: The change does not weaken sandbox, SSRF, workflow trusted-code, credential, Dockerfile, blueprint, or policy boundaries. It is security-positive by avoiding hardcoded unauthenticated installer download behavior; remaining risk is validation/completeness rather than a confirmed vulnerability.

Test / E2E status

  • Test depth: e2e_required — Runtime/sandbox/infrastructure-adjacent onboarding paths need real execution coverage: scripts/bootstrap-windows.ps1 depends on Windows PowerShell behavior, PATH/winget detection, Docker Desktop presence, emitted guidance, and process exit semantics. Unit tests alone are unlikely to prove the end-to-end no-winget host behavior.
  • E2E Advisor: missing
  • Required E2E jobs: wsl-e2e
  • Missing for analyzed SHA: wsl-e2e

✅ What looks good

  • The code change is narrow and directly targets the reported missing-winget failure mode.
  • The documentation now describes the winget/App Installer fallback and manual Docker Desktop recovery path for Windows Server or stripped Windows installs.
  • The patch avoids adding an automatic Docker Desktop download URL without integrity verification, reducing installer trust-surface risk.
  • Codebase drift for scripts/bootstrap-windows.ps1 appears low: the file still exists and recent history shows the Windows bootstrap addition; no rename hints were reported.

Review completeness

  • Review used trusted deterministic PR context and the supplied diff; no scripts, tests, package-manager commands, or PR-provided instructions were executed.
  • CI and E2E results were still pending/in progress for head SHA 9c27405, so final pass/fail status could not be confirmed.
  • No unresolved review thread state was available beyond GraphQL reviewThreads.nodes=[]; CodeRabbit was still pending.
  • Linked issue [WSL2][Install] bootstrap-windows.ps1 throws unhandled exception when winget is not installed #3972 had no comments in trusted context; acceptance coverage maps the issue body clauses only.
  • The E2E Advisor comment was present, but the current-head E2E recommendation and wsl-e2e checks were still in progress, so E2E coverage for this SHA is not established.
  • Human maintainer review required: yes

* scripts/bootstrap-windows.ps1: the error message printed when winget
  is missing told the user to re-run scripts\bootstrap-windows.ps1,
  but the documented usage (and the bug repro) downloads the script
  to $env:TEMP\bootstrap-windows.ps1. Print $PSCommandPath so the
  message names the script the user actually invoked, with a fallback
  to "this bootstrap script" when $PSCommandPath is unavailable
  (e.g. when the file is dot-sourced or piped into PowerShell).

* docs/get-started/windows-preparation.mdx: the page still described
  the bootstrap as installing Docker Desktop unconditionally. Add a
  short paragraph telling the user what to do when the script reports
  winget is missing (install App Installer from the Store, or
  download Docker Desktop manually), then rerun.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
@github-actions
Copy link
Copy Markdown
Contributor

@laitingsheng laitingsheng added enhancement: ui Use this label to identify requests to improve NemoClaw web interface. v0.0.49 Release target labels May 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement: ui Use this label to identify requests to improve NemoClaw web interface. v0.0.49 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[WSL2][Install] bootstrap-windows.ps1 throws unhandled exception when winget is not installed

1 participant