This is a follow-up to my original post, Installing OpenClaw on a Jetson Nano, where I got things working with Bun on Ubuntu 18.04. That setup ran fine for a few weeks — until I tried to upgrade.
Why upgrade? Link to heading
The original Bun-based install (2026.2.6) was working fine, but I wanted access to newer features — improved Telegram handling, cron job fixes, better model fallback chains, and the new adaptive thinking defaults for Claude. OpenClaw moves fast, and staying weeks behind means missing meaningful improvements.
What should have been a routine bun install -g openclaw@latest turned into a multi-day saga involving a 27-hour Node compilation, a Docker detour, crash-looping systemd services, and an AI cron job that forgot to stop checking on a build that had already finished.
The end state: OpenClaw 2026.3.1 running on Node 22.22.0 compiled from source, with a proper systemd service and full host access. Here’s how I got there.
Why Bun stopped working Link to heading
Starting around OpenClaw 2026.2.26, the project tightened plugin manifest validation. Manifests outside expected trust boundaries are now rejected as unsafe. On my Jetson, Bun’s global install layout (~/.bun/install/global/node_modules/...) tripped those checks for every single plugin:
unsafe plugin manifest path: /home/.../.bun/install/global/node_modules/openclaw/extensions/.../openclaw.plugin.json
The gateway refused to boot. The systemd service crash-looped — I later found it had hit 408 restart cycles before I noticed. The Node global path (~/.nvm/versions/node/.../lib/node_modules/...) doesn’t have this problem, so the fix was clear: move to Node. The problem was I didn’t have Node 22 on this machine.
The Docker detour Link to heading
My first attempt was the easy route: run OpenClaw in a Docker container (Debian Bookworm with Node 22). This worked, but meant losing direct host access — no tmux pane scraping, no camera access, none of the system-level integrations that make running on the Jetson Nano interesting in the first place. More importantly, I wanted OpenClaw to be able to upgrade itself and manage system packages on the host — things a containerised agent simply can’t do without privileged access that defeats the purpose of containerisation. So I went back to host-native, which meant building Node 22 from source.
Compiling Node 22 on a Jetson Nano Link to heading
The Jetson Nano runs an old L4T Ubuntu 18.04 with kernel 4.9. Distro packages are ancient, prebuilt Node 22 binaries don’t target this platform, and Snap’s Node has glibc mismatches. Building from source was the only option.
27 hours of compilation Link to heading
The final successful build took ~27 hours 15 minutes wall-clock time (started Feb 28 ~15:28 GMT, finished Mar 1 ~18:43 GMT). With earlier failed attempts, the total investment was over 30 hours.
The cc1plus processes consumed up to 3.6GB of swap during V8 compilation. I started conservatively with make -j2, then switched to make -j4 after a restart — risky with 4GB RAM, but it held.
The MTE patch Link to heading
Midway through, the build died with an assembler error:
Error: unknown architectural extension 'memtag'
This happened compiling deps/v8/src/heap/base/memory-tagging.cc. The Jetson Nano’s older GCC/binutils doesn’t support ARMv8.5-A Memory Tagging Extension instructions — and the Nano’s Cortex-A57 doesn’t have the feature anyway. The fix was a one-line patch:
- #define SUPPORTS_MTE V8_OS_LINUX && V8_HOST_ARCH_ARM64
+ #define SUPPORTS_MTE 0
The build that died in its sleep Link to heading
Around 5 AM on March 1st, the build silently stopped — likely OOM-killed or a process exit with no trace in the logs. I only caught this because I’d set up an OpenClaw cron job to check the build every hour by scraping the tmux pane output. The cron detected the dead session and restarted the build automatically.
That same cron job became a running joke: after the build finished at 18:43, it kept dutifully checking every hour for another 10+ hours, reporting “build still complete” into the early morning. Lesson learned: always add a stop condition to monitoring jobs.
The hourly monitoring also burned through my Gemini 3.1 Pro free tier quota (429 RESOURCE_EXHAUSTED) from all the context-heavy tmux log analysis, forcing a fallback to Claude Opus. Automated monitoring has token costs.
What made the build survivable Link to heading
- Always use tmux for long builds (
tmux new -s node22build). SSH disconnects are inevitable over 27 hours. - Don’t touch unrelated services while the compile is running. Memory pressure is already maxed out.
- Pin the binary path once it’s done (
~/.nvm/versions/node/v22.22.0/bin/node) to prevent falling back to an older system node.
Installing OpenClaw on Node 22 Link to heading
With Node 22 compiled, the next step was getting OpenClaw installed cleanly. This was harder than it should have been.
Partial installs break everything Link to heading
After interrupted upgrades, OpenClaw would start but tool execution would fail with missing modules:
Cannot find module '.../tool-loop-detection-....js'
imported from '.../subagent-registry-....js'
At one point, npm also failed due to stale temp directories:
ENOTEMPTY: directory not empty, rename .../openclaw -> .../.openclaw-...
The only reliable fix was a clean reinstall: delete the entire package directory, clear any .openclaw-* temp dirs, and install fresh.
The working recipe Link to heading
1. Stop the service and clean up:
sudo systemctl stop openclaw-gateway.service
cd ~/.nvm/versions/node/v22.22.0/lib/node_modules
rm -rf openclaw .openclaw-*
2. Install fresh:
~/.nvm/versions/node/v22.22.0/bin/npm install -g [email protected] \
--ignore-scripts --no-audit --no-fund
3. Verify before restarting:
grep '"version"' ~/.nvm/versions/node/v22.22.0/lib/node_modules/openclaw/package.json
~/.nvm/versions/node/v22.22.0/bin/node -e \
'import(process.env.HOME + "/.nvm/versions/node/v22.22.0/lib/node_modules/openclaw/dist/entry.js").then(()=>console.log("ok"))'
4. Use explicit paths in systemd:
# /etc/systemd/system/openclaw-gateway.service
ExecStart=/home/YOUR_USER/.nvm/versions/node/v22.22.0/bin/node \
/home/YOUR_USER/.nvm/versions/node/v22.22.0/lib/node_modules/openclaw/openclaw.mjs \
gateway run --port 18789 --bind loopback
Using openclaw via shebang can pick the wrong node. Explicit paths remove all ambiguity.
5. Restart and validate:
sudo systemctl daemon-reload
sudo systemctl restart openclaw-gateway.service
systemctl status --no-pager openclaw-gateway.service
curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:18789/__openclaw__/canvas/
Expected: service active (running), HTTP 200.
Your data survives all of this Link to heading
One reassuring thing throughout: the important state lives under ~/.openclaw — config, memory, agents, Telegram session data. Reinstalling the binary package doesn’t touch any of it. The only thing that kept breaking was the runtime package tree.
I now take a backup before any aggressive reinstall anyway:
tar -czf ~/openclaw-state-backup-$(date +%F-%H%M).tar.gz ~/.openclaw
What’s new in 2026.3.1 Link to heading
Since this post covers the full migration, here are the relevant changes in the version I landed on:
- Adaptive thinking: Claude 4.6 models now default to
adaptivethinking (previouslylow). Uses more tokens but produces better reasoning. - Cron timer hot-loop guard: prevents event-loop saturation from stale past-due jobs. Would have saved me from the runaway build-monitoring cron.
- Telegram fixes: voice caption overflow fallback, better reply chunking, DM topic session isolation.
NO_REPLYstripping: mixed-content messages no longer leak raw control tokens to users.- Breaking (minor for this setup): Node exec approval payloads now require
systemRunPlan, andsystem.runpins commands to canonical paths.
Takeaways Link to heading
- On Jetson Nano, prefer a clean reinstall over in-place upgrades when things get weird.
- Keep OpenClaw on the Node global path, not Bun, for
2026.2.26+releases. - If tools fail with missing module imports, suspect a partial install before touching config.
- Always run long builds in tmux — and kill the sessions when you’re done. I found stale ones running days later.
- Add stop conditions to monitoring cron jobs. “Check until done, then stop” beats “check forever.”
- Back up
~/.openclawbefore upgrades. The binary is replaceable; your memory and config aren’t.