Missing Control UI Assets on Global Install
Known Bug in npm Global Installs
Tracked in openclaw/openclaw#4855. After npm install -g openclaw, opening the dashboard shows "Missing Control UI assets" even though the files exist in the package. The issue is in the path resolution logic, not missing files.
http://127.0.0.1:18789/ returns Not Found).You ran npm install -g openclaw, the gateway starts fine, the dashboard URL appears — but visiting it shows "Missing Control UI assets. Build them with pnpm ui:build." Running pnpm ui:build fails because the source config doesn't exist in the published package.
Next Step
Fix now, then reduce repeat incidents
If this issue keeps coming back, validate your setup in Doctor first, then harden your config.
Jump to Section
What the Error Looks Like
When you open the Control UI URL in your browser or run openclaw doctor:
The confusing part: the error tells you to run pnpm ui:build, but that command is for developers building from source. It doesn't work on an installed npm package because the Vite config and source files aren't shipped.
Why This Happens
Entry point path assumption
The function resolveControlUiDistIndexPath() checks if process.argv[1] points inside a dist/ directory. With global npm install, the entry point is openclaw.mjs at the package root — not inside dist/. So the function returns null.
Fallback search is dev-only
When the primary path fails, the code searches upward for ui/vite.config.ts — a file that exists only in the source repo, never in the published npm package. This fallback was designed for local development, not production installs.
Assets are there, just not found
The actual control-ui files (index.html, JS bundles, CSS) are correctly included in the npm package under dist/control-ui/. You can verify with ls. The only problem is the resolver logic cannot locate them.
Confirm the Assets Exist
Before applying a fix, verify the assets are actually in the package. If they're missing, you have a different problem.
ls $(npm root -g)/openclaw/dist/control-ui/
ls $(npm root -g)/openclaw/dist/control-ui/
You should see index.html, assets/, favicon.ico, and other web files. If you see them, the fix below will work. If the directory doesn't exist at all, try reinstalling: npm install -g openclaw@latest.
Fix A: Symlink Workaround (Quick)
Create a symlink so the resolver's fallback path finds the assets. This is the fastest fix and survives gateway restarts, but you'll need to redo it after upgrading the package.
OPENCLAW_ROOT=$(npm root -g)/openclaw # The resolver expects assets relative to the dist entry point ln -sf "$OPENCLAW_ROOT/dist/control-ui" "$OPENCLAW_ROOT/control-ui" # Restart gateway to pick up the change openclaw gateway restart
Fix B: Install from Source
If you need a permanent fix or want the latest patches, clone the repo and run from source. This bypasses the npm packaging entirely.
git clone https://github.com/openclaw/openclaw.git cd openclaw pnpm install pnpm ui:build pnpm start
Running from source requires pnpm and Node 22+. If you were using npm global install specifically for simplicity, Fix A (symlink) is more appropriate.
Fix C: Use npx Instead of Global Install
npx runs the package in a temporary directory layout that may resolve the path correctly in some Node versions. It also always uses the latest version.
npx openclaw@latest gateway start
The trade-off: npx downloads the package on first run (slower startup), and you need to use npx openclaw everywhere instead of just openclaw.
Verify the Dashboard Loads
After applying any fix, confirm the Control UI is accessible:
Expected: Status: running — no "Missing Control UI" in output
Expected: Open http://localhost:18789 — you should see the Control UI login screen
Expected: Control UI check passes (green checkmark)
Still Stuck?
If the symlink didn't work, check exactly where the resolver is looking:
node -e "console.log(process.argv[1])" $(which openclaw) # Compare with: ls $(npm root -g)/openclaw/dist/control-ui/index.html
If process.argv[1] doesn't point inside the openclaw package at all (e.g., it points to a wrapper shim), the symlink needs to go in the shim's parent directory instead.
Run the Doctor
Checks Control UI asset paths, gateway health, and package layout.
Related Issues
Other install & setup problems:
Fix It Faster With Our Tools
Did this guide solve your problem?