#help
1 messages · Page 1 of 1 (latest)
That error is coming from OpenClaw’s tool-call wrapper (pi-tools “before tool call” hook). If the gateway can’t import pi-tools.before-tool-call.runtime…, it’ll break every tool (read/write/exec/etc) regardless of model/provider — so Gemini is a red herring here.
The two likely causes are:
- Broken/partial npm install (or a bad 2026.3.12 publish) → the
dist/*pi-tools.before-tool-call.runtime*chunk isn’t present. - macOS launchd / nvm mismatch → your shell runs one
openclaw, but the daemon is running a different Node + global module dir that’s missing files.
Can you run these and paste the output?
which openclaw
openclaw --version
node -v
# show where the global package lives (npm)
npm root -g
ls -la "$(npm root -g)/openclaw/dist" | grep -i "pi-tools.before-tool-call.runtime" || true
# if you used pnpm for globals instead of npm:
pnpm root -g 2>/dev/null && ls -la "$(pnpm root -g)/openclaw/dist" | grep -i "pi-tools.before-tool-call.runtime" || true
Quick workaround to get unblocked: try pinning to the last known-good build (2026.3.11) and restart the gateway:
npm i -g openclaw@2026.3.11
openclaw gateway restart
If 2026.3.11 fixes it, then 2026.3.12 is almost certainly a packaging regression — please open a GitHub issue with the outputs above + the exact “Cannot find module … imported from …” line from logs so it can be patched: https://github.com/openclaw/openclaw/issues
Yep — that’s a broken dist set: pi-embedded-C6ITuRXf.js is trying to import("./pi-tools.before-tool-call.runtime-C_SzfJuR.js"), but that chunk isn’t on disk. That can only happen if the published/install artifact is missing files or something local is deleting/skipping specific files during install.
1) First: verify whether the npm tarball itself contains the missing chunk
Run this in any temp dir:
npm config get registry
npm -v
npm pack openclaw@2026.3.11
tar -tf openclaw-2026.3.11.tgz | grep "pi-tools.before-tool-call.runtime" | sort
tar -tf openclaw-2026.3.11.tgz | grep "C_SzfJuR" || echo "C_SzfJuR not in tarball"
- If
C_SzfJuRis not in the tarball → that’s an npm publish bug (missing chunk). Please open a GitHub issue and paste the output above + the exact error line. - If
C_SzfJuRis in the tarball but not on disk after install → something on the machine is removing or failing to write that file (permissions, “cleanup” tools, corporate endpoint protection, etc.).
2) Quick “get unstuck” workaround (hacky but should work)
Since those pi-tools.before-tool-call.runtime-*.js files are the same module under different hashes, you can duplicate one to the missing filename:
cd /usr/local/lib/node_modules/openclaw/dist
# pick one that exists on your machine (example uses aDuNkZiY)
cp pi-tools.before-tool-call.runtime-aDuNkZiY.js pi-tools.before-tool-call.runtime-C_SzfJuR.js
openclaw gateway restart
If that fixes tools immediately, it’s strong confirmation this is just a missing chunk file (not config/model).
3) If you do open an issue
Include:
openclaw --version,node -v,npm -v
npm config get registry- the
npm pack …/tar -tf …results - the exact error:
Cannot find module … imported from …
GitHub issues: https://github.com/openclaw/openclaw/issues
If …/dist/pi-embedded-C6ITuRXf.js truly doesn’t exist on disk anymore, then there is no magical Node “cache file” resurrecting it on a fresh start. That filename can only show up in logs if one of these is true:
- You still have a running gateway process that loaded
pi-embedded-C6ITuRXf.jsearlier (then you reinstalled and removed the file on disk, but the process is still alive), or - You’re actually connecting to / reading logs from a different gateway install/profile than the one you’re inspecting in
/usr/local/lib/node_modules/openclaw/…(extra launchd services are common on macOS).
The fastest way to prove which it is:
A) Ask the running gateway what it is
openclaw gateway call status
openclaw gateway call logs.tail --params '{"sinceMs": 120000}'
Paste the output. This will tell us which gateway instance you’re talking to right now.
B) Scan for “extra gateways” (this is exactly what --deep is for)
openclaw doctor --deep
If it reports multiple launchd services / profiles, remove the extras (or let doctor guide you). Docs: https://docs.openclaw.ai/gateway/doctor
C) Check launchd labels directly (macOS app can keep these alive)
launchctl list | egrep "openclaw|clawdbot|moltbot|com\\.openclaw|ai\\.openclaw"
ls -la ~/Library/LaunchAgents | egrep "openclaw|clawdbot|moltbot|com\\.openclaw|ai\\.openclaw"
On macOS the default label is ai.openclaw.gateway (or ai.openclaw.<profile>), and app quit does not stop the gateway if it’s installed as a LaunchAgent. Docs: https://docs.openclaw.ai/platforms/mac/bundled-gateway
Once we see which label(s) exist, the fix is usually:
openclaw gateway uninstall(and if there are profile services:openclaw --profile <name> gateway uninstall)- then
openclaw gateway install --force - then
openclaw gateway restart
Send the outputs from (A) + (B). That will pinpoint exactly where the stale filename is coming from.
Good — that confirms you’re talking to a real, running gateway (RPC works, sessions path is the default state dir, etc).
Now the key point:
There is no persistent “cache” in Node that can keep referencing pi-embedded-C6ITuRXf.js after a true process restart.
If you’re seeing errors “imported from …pi-embedded-C6ITuRXf.js” while that file no longer exists on disk, then you are almost certainly in one of these situations:
- the gateway process did not actually restart (old process is still alive with that module already loaded), or
- you have multiple launchd gateway services (old label/profile still running), and you’re restarting one but talking to another.
1) Prove whether restart is real (fast test)
Run:
openclaw gateway restart
openclaw gateway call logs.tail --params '{"sinceMs": 30000}'
You should see fresh “starting gateway …” style lines in that 30s window. If you don’t, your restart isn’t touching the running process.
2) Find all macOS launchd services that could be running gateways
openclaw doctor --deep
launchctl list | egrep "ai\\.openclaw|com\\.openclaw|clawdbot|moltbot"
ls -la ~/Library/LaunchAgents | egrep "ai\\.openclaw|com\\.openclaw|clawdbot|moltbot"
Paste those outputs. (The mac app docs explicitly mention legacy com.openclaw.* labels can remain, and the app can keep a LaunchAgent alive even if you reinstall the CLI.)
Docs for the “extra gateway installs” scan: https://docs.openclaw.ai/gateway/doctor
macOS launchd details: https://docs.openclaw.ai/platforms/mac/bundled-gateway
Once we see which labels exist, the cleanup is usually:
openclaw gateway uninstall(and if doctor shows profiles, alsoopenclaw --profile <name> gateway uninstall)- then
openclaw gateway install --force
- then
openclaw gateway restart
But the next step is: show me doctor --deep + the launchctl list, because that will immediately reveal the “ghost” service that’s still running old code.
If pi-embedded-C6ITuRXf.js is not on disk, there isn’t some hidden Node cache file that can “remember” it across a real restart. The only way you keep seeing:
imported from …/pi-embedded-C6ITuRXf.js
is: the gateway process that originally loaded that module is still running (and you later removed/changed files on disk), or you’re connected to a different gateway than the filesystem you’re inspecting.
Since launchctl list shows nothing, the gateway is very likely a stray background node …openclaw… process, not launchd-managed right now.
Find the actual running gateway PID (by port) and see what it’s executing
(Default port is usually 18789.)
sudo lsof -nP -iTCP:18789 -sTCP:LISTEN
# note the PID, then:
ps -p <PID> -o pid,command
That command line will tell us exactly which openclaw.mjs / install path it’s running from (and whether it’s an old path).
Then stop it by PID:
kill <PID>
# if it refuses:
kill -9 <PID>
Re-run the lsof …18789… command to confirm it’s gone.
After it’s really dead, re-install + re-enable the launchd service
openclaw gateway install --force
openclaw gateway start
launchctl print gui/$(id -u)/ai.openclaw.gateway | head -40
Then immediately check fresh logs:
openclaw gateway call logs.tail --params '{"sinceMs": 30000}'
If you paste the lsof line + the ps …command line, we can confirm exactly where the stale pi-embedded-C6ITuRXf.js reference is coming from.
Node/macOS isn’t caching “compiled ESM modules” in a way that can invent new import targets after a real process restart.
What you’re seeing:
Cannot find module …runtime-C_SzfJuR.js' imported from …/pi-embedded-C6ITuRXf.js
means the running Node process has an in‑memory ESM module record whose URL is …/pi-embedded-C6ITuRXf.js, and that code contains the hard-coded dynamic import for …runtime-C_SzfJuR.js. That string cannot come from a session transcript. V8 caches don’t rewrite import specifiers, and they don’t survive in a way that would let Node load a parent module that isn’t on disk.
So if pi-embedded-C6ITuRXf.js “doesn’t exist anywhere”, one of these must be true:
- The gateway process loaded it earlier and it was deleted afterwards (process stayed alive), or
- You’re looking at old logs, or
- You’re actually connecting to a gateway process running from a different filesystem path than you think.
The fastest way to settle it: check what files the running gateway process has open
Get the gateway PID (replace port if you changed it):
sudo lsof -nP -iTCP:18789 -sTCP:LISTEN
Then:
ps -p <PID> -o pid,etime,command
sudo lsof -p <PID> | egrep "openclaw/dist/pi-embedded|pi-tools\\.before-tool-call\\.runtime" | head
- If
lsof -pshowspi-embedded-C6ITuRXf.js(often it’ll show as deleted), that proves it was loaded before it disappeared from disk → you need to kill that PID and start a fresh gateway. - If it shows no
openclaw/distfiles at all, then you’re not inspecting the right process / the logs are stale.
If you paste:
- the single
lsof …LISTENline, ps …etime,command,
- and the
lsof -p … | egrep …output,
we can pinpoint exactly where that stale parent module is coming from.
Those /tmp/openclaw*/openclaw-YYYY-MM-DD.log files are just log rotation (the gateway’s stdout/err). They’re not a code cache, and they can’t “bake in” an import path. Session transcripts also can’t do this — they’re JSON data, never executed as modules.
On the caching question:
- ESM module caching is in-memory only (per-process).
- Even if there were a V8 bytecode cache, it doesn’t create or change import specifiers. The string
pi-embedded-C6ITuRXf.jsmust come from the already-loaded JS module code (or from old log lines).
So the actionable path now is: use those logs to extract the current PID and confirm whether it’s an old still-running process vs stale log lines.
1) Confirm the error is happening now (not just sitting in old logs)
Right after triggering a tool call that fails, run:
openclaw gateway call logs.tail --params '{"sinceMs": 5000}'
2) Pull the exact PID + “imported from …” lines from today’s log
rg -n "pi-embedded-|before-tool-call\\.runtime|Cannot find module" /tmp/openclaw/openclaw-2026-03-13.log | tail -50
If the log format includes a PID, paste it. If it doesn’t, we’ll get PID via the listening port.
3) One more important check: system-domain launchd (needs sudo)
It’s possible to have a gateway running as a system service even if user launchctl list is empty:
sudo launchctl list | egrep "openclaw|clawdbot|moltbot|ai\\.openclaw|com\\.openclaw" || true
sudo ls -la /Library/LaunchDaemons | egrep "openclaw|clawdbot|moltbot|ai\\.openclaw|com\\.openclaw" || true
If you paste:
- the
logs.tailoutput (5s window), - the
rg … openclaw-2026-03-13.log …lines,
- and the
sudo launchctl listgrep result,
we can definitively tell whether you’re dealing with (a) an actually-running old process that has pi-embedded-C6ITuRXf.js loaded in memory, or (b) stale log content / a different gateway domain.
Yep — easiest on macOS is lsof.
Get the PID listening on 18789
sudo lsof -nP -iTCP:18789 -sTCP:LISTEN
You’ll get something like:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 1234 you ... TCP ... LISTEN
Then inspect exactly what it’s running
ps -p <PID> -o pid,etime,command
sudo lsof -p <PID> | head -50
If it’s really “old 3.8-era” code, ps …command / lsof -p will usually reveal the actual on-disk path it originally launched from (often you’ll see a deleted path / old install dir).
Kill it (and verify the port stays closed)
sudo kill <PID>
sleep 1
sudo lsof -nP -iTCP:18789 -sTCP:LISTEN || echo "18789 is free"
If it immediately comes back with a new PID, something is supervising it (not launchd in your user/system domains) — paste the ps -p …command line and we can track down what’s respawning it.
There it is — PID 11242 is the “ghost” gateway. Next step is to see what exact OpenClaw path that node process is running, then kill it and bring up a fresh gateway from your current install.
1) Show command line + uptime + parent
ps -p 11242 -o pid,ppid,etime,command
ps -p $(ps -p 11242 -o ppid=) -o pid,command
2) See which OpenClaw files it actually has open (this is the smoking gun)
sudo lsof -p 11242 | egrep "openclaw|clawdbot|moltbot|pi-embedded|logger-" | head -80
If you see paths that no longer exist (or an old install dir), that explains the “imports old hashed files that aren’t on disk anymore” behavior.