The Token Mismatch Error
You’ve been running OpenClaw happily on your Azure VM, configs changed, gateway restarted multiple times — then suddenly you see this in the logs:
2026-02-26T00:00:15.484Z [ws] unauthorized conn=f5c5408b-6704-4451-8e6d-858fb7052533
remote=127.0.0.1 client=gateway-client backend vdev reason=token_mismatchFollowed immediately by:
2026-02-26T00:00:15.487+00:00 gateway connect failed:
Error: unauthorized: gateway token mismatch (provide gateway auth token)And the connection is torn down:
2026-02-26T00:00:15.505Z [ws] closed before connect
conn=f5c5408b-6704-4451-8e6d-858fb7052533 remote=127.0.0.1
fwd=n/a origin=n/a host=127.0.0.1:18789 ua=n/a
code=1008 reason=unauthorized: gateway token mismatch (provide gateway auth token)This is a WebSocket-level authentication failure — the client tried to connect to the gateway but presented a stale or wrong auth token.
How Gateway Tokens Work
OpenClaw uses a token-based authentication system for all WebSocket connections to the gateway. When the gateway starts, it reads (or generates) an auth token stored in its state directory:
~/.openclaw/credentials/Every client connecting to ws://0.0.0.0:18789 must present this token. That includes:
- The CLI (
openclaw-cli) when executing commands via the gateway - The Control UI dashboard
- Paired devices (phones, other machines)
- Internal gateway-client connections (backend services)
Why Token Mismatch Occurs
The most common scenarios:
1. Token Regenerated After Restart
If the gateway regenerates its token on startup (due to missing or corrupted credential files), all previously-connected clients still hold the old token.
2. Multiple Config/Restart Cycles
In a session like the one shown in the terminal output where you run many config set commands followed by docker compose restart, the gateway may cycle through multiple restarts. If a background client was connected to a previous instance, it reconnects with an outdated token:
# Rapid config changes — each followed by restart
docker compose run --rm openclaw-cli config set agents.defaults.memorySearch.provider local
docker compose run --rm openclaw-cli config set agents.defaults.memorySearch.model all-MiniLM-L6-v2
# ... 7 more config sets ...
docker compose restart openclaw-gateway3. Dev vs Production Profile Mismatch
Running openclaw --dev gateway isolates state under ~/.openclaw-dev/, generating a separate token. If you then connect a client configured for the production profile, it’s a guaranteed mismatch:
# Dev mode uses isolated state
openclaw --dev gateway # token in ~/.openclaw-dev/credentials/
openclaw gateway # token in ~/.openclaw/credentials/4. Docker Volume Token Persistence
If you rebuild the Docker image or recreate volumes, the in-container token at /home/node/.openclaw/credentials/ may differ from what paired devices remember:
# This preserves credentials:
docker compose restart openclaw-gateway
# This may regenerate credentials:
docker compose down && docker compose up -d5. Port Already in Use Forces a Down/Up Cycle
If a previous gateway process didn’t release 18789 cleanly, docker compose restart can fail with an “address already in use” or “port is already allocated” error. Working around that by running docker compose down and docker compose up -d instead of a plain restart is exactly the recreate path from scenario 4 above — it can regenerate the credentials directory and hand out a new token while old clients still hold the previous one.
docker compose restart openclaw-gateway
# Error: port is already allocated
# Workaround that can trigger a new token:
docker compose down && docker compose up -dDiagnosing the Problem
Step 1: Check the Gateway Logs
Filter for authentication-related events:
docker logs --tail=100 openclaw-openclaw-gateway-1 | \
grep -i "unauthorized\|token_mismatch\|closed before connect"Look for the reason=token_mismatch field — it confirms the token itself is wrong, not an origin or header issue.
Step 2: Inspect the Connection Details
The log line contains useful metadata:
| Field | Meaning |
|---|---|
conn=f5c5408b-... | Unique connection ID |
remote=127.0.0.1 | Client IP (localhost means internal) |
client=gateway-client | Which component tried to connect |
code=1008 | WebSocket close code (Policy Violation) |
ua=n/a | No User-Agent (internal client) |
Step 3: Check Current Token
From inside the container:
docker exec -it openclaw-openclaw-gateway-1 sh -lc \
'ls -la /home/node/.openclaw/credentials/'Or via CLI:
docker compose run --rm openclaw-cli config get gateway.authFixing the Mismatch
Option 1: Restart the Client
If the gateway token is correct and the client is stale, simply restart whatever client was trying to connect. For the internal gateway-client backend vdev:
docker compose restartOption 2: Re-pair Devices
If paired devices (phone, laptop) can’t connect:
# List all paired devices
docker compose run --rm openclaw-cli devices list
# Generate a new pairing code
docker compose run --rm openclaw-cli qrScan the new QR code from your device to re-authenticate with the current gateway token.
Option 3: Force Token Reset
If the token state is corrupted, you can force the gateway to regenerate:
# Stop the gateway
docker compose down openclaw-gateway
# Remove the credentials directory (it will be regenerated)
rm -rf ~/.openclaw/credentials/
# Restart — a new token is generated
docker compose up -d openclaw-gatewayWarning: This invalidates ALL existing connections and paired devices. Every client must re-authenticate.
Option 4: Copy Token to Client
If you’re connecting from another machine or a dev profile, copy the token manually:
# Read the current gateway token
docker compose run --rm openclaw-cli config get gateway.auth.token
# Set it on the client machine
openclaw config set gateway.auth.token <TOKEN_VALUE>Preventing Future Mismatches
1. Batch Config Changes
Instead of running multiple config set + restart cycles, batch your changes and restart once:
# All changes, then ONE restart
docker compose run --rm openclaw-cli config set agents.defaults.memorySearch.provider local
docker compose run --rm openclaw-cli config set agents.defaults.memorySearch.model all-MiniLM-L6-v2
docker compose run --rm openclaw-cli config set agents.defaults.memorySearch.cache.enabled true
# ... more config sets ...
# Single restart at the end
docker compose restart openclaw-gatewayMany settings are hot-reloaded anyway — check the gateway logs for [reload] config change applied messages before restarting unnecessarily.
2. Use restart Instead of down/up
docker compose restart preserves the container’s state directory. Avoid docker compose down unless you intend to recreate containers:
# Preserves token:
docker compose restart openclaw-gateway
# May generate new token:
docker compose down && docker compose up -d3. Persist Credentials in Named Volumes
Ensure your docker-compose.yml maps a named or bind-mount volume for the .openclaw directory:
services:
openclaw-gateway:
volumes:
- /home/azureuser/.openclaw:/home/node/.openclawThis ensures credentials survive container recreation.
4. Monitor WebSocket Health
Add a health check that watches for token errors:
#!/bin/bash
# check-ws-auth.sh
ERROR_COUNT=$(docker logs --tail=50 openclaw-openclaw-gateway-1 2>&1 | \
grep -c "token_mismatch")
if [ "$ERROR_COUNT" -gt 0 ]; then
echo "WARNING: $ERROR_COUNT token mismatch errors in recent logs"
fiWebSocket Close Codes Reference
| Code | Meaning | Common Cause |
|---|---|---|
| 1000 | Normal closure | Clean disconnect |
| 1006 | Abnormal closure | Network drop, container killed |
| 1008 | Policy violation | Token mismatch, origin rejected |
| 1011 | Unexpected condition | Internal server error |
The code=1008 in our error maps to a policy violation — the gateway rejected the connection because the authentication didn’t pass.
Series Navigation
Previous: Building a Persistent AI Agent Memory System with OpenClaw Next: OpenClaw Agent Tool Execution Errors and Sandbox Permissions
Part 26 of the OpenClaw on Azure series. Your gateway’s locked tight — just make sure you’ve got the right key.



