#10589: fix: chrome extension install fails in bundled dist layout
cli
stale
Cluster:
Browser Extension Fixes
## Problem
`openclaw browser extension install` fails with:
```
Bundled Chrome extension is missing. Reinstall OpenClaw and try again.
```
...even though `assets/chrome-extension/manifest.json` exists at the package root.
## Root Cause
`resolveBundledExtensionRootDir()` has a walk-up loop that searches parent directories for `assets/chrome-extension`, with a hardcoded fallback of `../../assets/chrome-extension`.
The bundler (Rollup/esbuild) tree-shakes the walk-up loop, leaving only the hardcoded fallback. This fallback is correct for the **source** layout (`src/cli/` = 2 levels deep) but wrong for the **bundled** layout (`dist/` = 1 level deep):
| Layout | `here` | `../../assets/chrome-extension` resolves to |
|--------|--------|----------------------------------------------|
| Source | `src/cli/` | `./assets/chrome-extension` ✅ |
| Bundled | `dist/` | `../assets/chrome-extension` ❌ (one level above package root) |
## Fix
Add a secondary fallback after the walk-up loop that tries both `../../` and `../` relative offsets with `manifest.json` existence checks. This is resilient to tree-shaking since it doesn't depend on the loop surviving bundling — both candidate paths are checked at runtime.
## Test
Added a test case for the flat `dist/` (bundled) layout alongside the existing `src/cli/` tests.
## Verified
Manually patched the compiled `dist/` files on a Homebrew-installed OpenClaw 2026.2.3-1 (macOS, Apple Silicon) and confirmed `openclaw browser extension install` succeeds after the fix.
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
- Updates `resolveBundledExtensionRootDir()` to locate the bundled Chrome extension assets by walking up from the runtime directory and adding a second runtime-checked fallback for `dist/` layouts.
- Adds a new unit test that simulates the “flat dist directory” bundled layout (`root/dist`) and asserts the resolver returns the package-root `assets/chrome-extension`.
- Keeps existing behavior for the final default path so the caller’s error message remains unchanged when no manifest is found.
<h3>Confidence Score: 3/5</h3>
- Logic change is localized, but the accompanying tests contain at least one runtime error and should be fixed before merge.
- The resolver change is straightforward and low blast-radius, but `src/cli/browser-cli-extension.test.ts` currently calls `vi.resetModules()` which is undefined in this repo’s Vitest environment, causing test failures. Fixing the test should bring confidence back up; no other definite functional regressions were found in the changed resolver logic.
- src/cli/browser-cli-extension.test.ts
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#10937: fix(browser): correct fallback path for bundled Chrome extension
by dddabtc · 2026-02-07
91.3%
#9398: Fix browser extension install path calculation
by vishaltandale00 · 2026-02-05
87.3%
#9796: fix(cli): correct fallback path for bundled Chrome extension (#9772)
by lailoo · 2026-02-05
87.2%
#9259: Fix: Restore explicit glob patterns in package.json files field
by vishaltandale00 · 2026-02-05
79.3%
#20424: Fix plugin extension path traversal in discovery/install
by markmusson · 2026-02-18
77.3%
#14944: fix(browser): prefer openclaw profile in headless/noSandbox environ...
by BenediktSchackenberg · 2026-02-12
76.7%
#13176: fix: resolve llm-task module import for global installs
by striking · 2026-02-10
76.4%
#10367: CLI/Ops: resilient browser fill + failover hardening + operations t...
by cluster2600 · 2026-02-06
75.6%
#23139: test: fix flaky auth tests when OPENCLAW_GATEWAY_TOKEN is present
by Imccccc · 2026-02-22
75.0%
#6193: fix(browser): default to openclaw profile instead of chrome extensi...
by mikezaoldyeck · 2026-02-01
74.9%