If you’re running OpenClaw and suddenly start seeing this:
gateway closed (1008): unauthorized: device token mismatch (rotate/reissue device token)Don’t panic. I spent way too long on this today. Here’s the fix so you don’t have to.
The Symptom
After updating to v2026.2.15, openclaw gateway status started showing:
RPC probe: failed
gateway closed (1008): unauthorized: device token mismatch (rotate/reissue device token)openclaw doctor — didn’t detect it
openclaw gateway restart — same error
Deleting device identity files and re-pairing — still broken
Multiple reboots — nope
The Cause
OpenClaw stores a gateway auth token in two places:
~/.openclaw/openclaw.json— undergateway.auth.token- The service file that keeps the gateway running in the background — as the
OPENCLAW_GATEWAY_TOKENenvironment variable
The service file location depends on your OS:
| OS | Service file |
|---|---|
| Linux (systemd) | ~/.config/systemd/user/openclaw-gateway.service |
| macOS (launchd) | ~/Library/LaunchAgents/ai.openclaw.gateway.plist (or legacy com.openclaw.gateway.plist) |
At some point (likely during an update or config change), these two values got out of sync. The CLI reads one token, the gateway process uses the other, and they reject each other.
The Fix (Linux)
I’m sure an actual fix is coming. For now, you need to make sure that these two auth tokens match.
Check it out with (or just ask OpenClaw to reconcile them):
# Get the token from openclaw.json
python3 -c "import json; c=json.load(open('$HOME/.openclaw/openclaw.json')); print(c['gateway']['auth']['token'])"
# Get the token from the systemd service
grep OPENCLAW_GATEWAY_TOKEN ~/.config/systemd/user/openclaw-gateway.serviceIf they’re different, that’s your problem. Copy the token from openclaw.json into the systemd service file:
# Edit the service file
nano ~/.config/systemd/user/openclaw-gateway.service
# Find the line:
# Environment=OPENCLAW_GATEWAY_TOKEN=<old_token>
# Replace <old_token> with the token from openclaw.json
# Reload and restart
systemctl --user daemon-reload
systemctl --user restart openclaw-gateway
# Wait ~20 seconds for the Pi (faster on beefier hardware)
sleep 20
openclaw gateway statusYou should see RPC probe: ok and everything works again.
The Fix (macOS)
Same idea, different file location and restart commands.
Check if they match:
# Get the token from openclaw.json
python3 -c "import json; c=json.load(open('$HOME/.openclaw/openclaw.json')); print(c['gateway']['auth']['token'])"
# Get the token from the launchd plist
grep -A1 OPENCLAW_GATEWAY_TOKEN ~/Library/LaunchAgents/ai.openclaw.gateway.plistNote: If you don’t have
ai.openclaw.gateway.plist, check for the legacy name:com.openclaw.gateway.plist. You can find yours with:ls ~/Library/LaunchAgents/ | grep -i openclaw
If the tokens don’t match, edit the plist:
# Edit the plist
nano ~/Library/LaunchAgents/ai.openclaw.gateway.plist
# Find the OPENCLAW_GATEWAY_TOKEN entry and replace the value
# with the token from openclaw.json
# Unload and reload the service
launchctl unload ~/Library/LaunchAgents/ai.openclaw.gateway.plist
launchctl load ~/Library/LaunchAgents/ai.openclaw.gateway.plist
# Verify
openclaw gateway statusYou should see RPC probe: ok.
Why This Happens
Best I can tell, OpenClaw rotates or regenerates the gateway token in openclaw.json during certain operations (updates, config changes, doctor --fix), but doesn’t always update the service file (systemd or launchd) to match.
At the moment, this is a known issue in version 2026.2.15.
Could be fixed tomorrow, but for now this will get you squared away.
Quick Diagnostic One-Liner
Linux
JSON_TOKEN=$(python3 -c "import json; c=json.load(open('$HOME/.openclaw/openclaw.json')); print(c['gateway']['auth']['token'])")
SERVICE_TOKEN=$(grep -oP 'OPENCLAW_GATEWAY_TOKEN=\K.*' ~/.config/systemd/user/openclaw-gateway.service)
[ "$JSON_TOKEN" = "$SERVICE_TOKEN" ] && echo "✅ Tokens match" || echo "❌ Tokens DON'T match — that's your problem"macOS
JSON_TOKEN=$(python3 -c "import json; c=json.load(open('$HOME/.openclaw/openclaw.json')); print(c['gateway']['auth']['token'])")
PLIST_TOKEN=$(grep -A1 OPENCLAW_GATEWAY_TOKEN ~/Library/LaunchAgents/ai.openclaw.gateway.plist | tail -1 | sed 's/.*<string>\(.*\)<\/string>.*/\1/')
[ "$JSON_TOKEN" = "$PLIST_TOKEN" ] && echo "✅ Tokens match" || echo "❌ Tokens DON'T match — that's your problem"Hope this saves someone a few hours.
This page may contain affiliate links. Please see my affiliate disclaimer for more info.