#cron status saying gateway is closed but gateway is open.

1 messages · Page 1 of 1 (latest)

desert bobcatBOT
#

That symptom (“openclaw gateway status is fine, but openclaw cron status says gateway closed (1000)”) usually means the gateway is up, but the CLI’s real RPC connection is getting immediately closed — and the reason only shows up in the gateway logs (auth/device pairing/token drift are the common causes).

Try this triage (in order):

  1. Watch logs while reproducing
openclaw logs --follow
# in another terminal:
openclaw cron status

Paste the few log lines around the close. The server will usually log something like AUTH_TOKEN_MISMATCH, PAIRING_REQUIRED, device token mismatch, etc.

  1. Check for a pending device pairing / scope upgrade
openclaw devices list
openclaw devices approve --latest
#

If you recently upgraded, it’s pretty common that the local CLI needs a new/updated operator device token and the gateway will close the socket until it’s approved.

Docs: https://docs.openclaw.ai/cli/devices

  1. Run doctor (it catches a lot of “it looks running but X is broken”)
openclaw doctor

If logs show token drift (AUTH_TOKEN_MISMATCH / AUTH_DEVICE_TOKEN_MISMATCH), follow the “token drift recovery checklist” on the devices page (rotate/remove/re-approve device token).

Relevant runbook section: https://docs.openclaw.ai/gateway/troubleshooting#cron-and-heartbeat-delivery

If you drop the log snippet from step (1), I can tell you exactly which branch it is.

exotic vine
#

Ran doctor and doctor --fix but still not able to connect. Can't even run openclaw devices list


🩞 OpenClaw 2026.3.12 (6472949) — Pairing codes exist because even bots believe in consent—and good security hygiene.

│
gateway connect failed: Error: gateway closed (1000): 
◇  
Error: gateway closed (1000 normal closure): no close reason
Gateway target: ws://127.0.0.1:18789
Source: local loopback
Config: /home/*****/.openclaw/openclaw.json
Bind: loopback
*****@OpenClaw:~$ openclaw devices list

🩞 OpenClaw 2026.3.12 (6472949) — Greetings, Professor Falken

│
gateway connect failed: Error: gateway closed (1000): 
◇  
[openclaw] Failed to start CLI: Error: gateway closed (1000 normal closure): no close reason
Gateway target: ws://127.0.0.1:18789
Source: local loopback
Config: /home/*****/.openclaw/openclaw.json
Bind: loopback
    at Object.onClose (file:///home/*****/.npm-global/lib/node_modules/openclaw/dist/auth-profiles-iXW75sRj.js:57890:10)
    at WebSocket.<anonymous> (file:///home/*****/.npm-global/lib/node_modules/openclaw/dist/auth-profiles-iXW75sRj.js:57019:23)
    at WebSocket.emit (node:events:519:28)
    at WebSocket.emitClose (/home/*****/.npm-global/lib/node_modules/openclaw/node_modules/ws/lib/websocket.js:273:10)
    at Socket.socketOnClose (/home/*****/.npm-global/lib/node_modules/openclaw/node_modules/ws/lib/websocket.js:1346:15)
    at Socket.emit (node:events:519:28)
    at TCP.<anonymous> (node:net:346:12)
*****@OpenClaw:~$ openclaw logs --follow

🩞 OpenClaw 2026.3.12 (6472949) — Pairing codes exist because even bots believe in consent—and good security hygiene.

gateway connect failed: Error: gateway closed (1000): 
Gateway not reachable. Is it running and accessible?
Gateway target: ws://127.0.0.1:18789
Source: local loopback
Config: /home/*****/.openclaw/openclaw.json
Bind: loopback
Hint: run `openclaw doctor`.
*****@OpenClaw:~$ ```
desert bobcatBOT
#

If every command that needs an authenticated WS RPC (cron, devices, logs --follow, etc.) dies with gateway closed (1000) but openclaw gateway status still shows RPC probe: ok, that almost always means:

the Gateway is enforcing auth (token/password), but your CLI process isn’t sending the right auth (missing token in your current shell, token drift, or gateway token coming from systemd/.env/SecretRef that your interactive shell can’t resolve).

1) Check auth config locally (doesn’t require connecting)

Run these and paste the output but DO NOT paste the actual token (redact it):

openclaw config get gateway.auth
openclaw config get gateway.auth.mode
openclaw config get gateway.auth.token

What I’m looking for:

  • mode: "token" with token set (or token coming from env/SecretRef)
  • or mode: "password" with password set

2) If token/password is coming from env, make sure your shell has it

#

Common case with systemd: the service gets ~/.openclaw/.env, but your shell doesn’t.

Check:

rg 'OPENCLAW_GATEWAY_(TOKEN|PASSWORD)=' ~/.openclaw/.env || true
systemctl --user show openclaw-gateway --property=Environment

If you find it in ~/.openclaw/.env, export it in your current shell (again: don’t paste it here) and retry:

export OPENCLAW_GATEWAY_TOKEN="
"
openclaw devices list

3) If you can’t recover the token: set a new one + restart

This will invalidate old UI sessions, but gets you unstuck:

#
openclaw config set gateway.auth.mode token
openclaw config set gateway.auth.token "$(openssl rand -hex 32)"
openclaw gateway restart

4) If you want the definitive reason: read the gateway’s file log directly

Since openclaw logs --follow can’t connect, tail the file mentioned by gateway status:

tail -n 200 /tmp/openclaw/openclaw-2026-03-13.log

If you drop the outputs from (1) + the tail from (4) (with secrets redacted), I can tell you exactly which of the above it is.

Refs:

exotic vine
#

still nothing. my token is stored as OPENCLAW_GATEWAY_TOKEN in .openclaw/.env. in my openclaw.json im referring to it as "token": "${OPENCLAW_GATEWAY_TOKEN}"

openclaw config get gateway.auth.mode
openclaw config get gateway.auth.token

🩞 OpenClaw 2026.3.12 (6472949) — Alexa, but with taste.

{
  "mode": "token",
  "token": "__OPENCLAW_REDACTED__"
}

🩞 OpenClaw 2026.3.12 (6472949) — I can't fix your code taste, but I can fix your build and your backlog.

token

🩞 OpenClaw 2026.3.12 (6472949) — I'm not saying your workflow is chaotic... I'm just bringing a linter and a helmet.

__OPENCLAW_REDACTED__
fhorst@OpenClaw:~$ nano .openclaw/.env 
fhorst@OpenClaw:~$ export OPENCLAW_GATEWAY_TOKEN="!MYTOKEN!"
fhorst@OpenClaw:~$ openclaw devices list

🩞 OpenClaw 2026.3.12 (6472949) — Type the command with confidence—nature will provide the stack trace if needed.

│
gateway connect failed: Error: gateway closed (1000): 
◇  
[openclaw] Failed to start CLI: Error: gateway closed (1000 normal closure): no close reason
Gateway target: ws://127.0.0.1:18789
Source: local loopback
Config: /home/fhorst/.openclaw/openclaw.json
Bind: loopback
    at Object.onClose (file:///home/fhorst/.npm-global/lib/node_modules/openclaw/dist/auth-profiles-iXW75sRj.js:57890:10)
    at WebSocket.<anonymous> (file:///home/fhorst/.npm-global/lib/node_modules/openclaw/dist/auth-profiles-iXW75sRj.js:57019:23)
    at WebSocket.emit (node:events:519:28)
    at WebSocket.emitClose (/home/fhorst/.npm-global/lib/node_modules/openclaw/node_modules/ws/lib/websocket.js:273:10)
    at Socket.socketOnClose (/home/fhorst/.npm-global/lib/node_modules/openclaw/node_modules/ws/lib/websocket.js:1346:15)
    at Socket.emit (node:events:519:28)
    at TCP.<anonymous> (node:net:346:12)```

I can share that tail log but I have no idea if there are sensitive items in there.
desert bobcatBOT
#

Yeah — don’t paste the whole gateway log into a public thread. It can contain bits you don’t want to share (URLs, chat snippets, sometimes headers, etc.). We can still debug this safely.

Two important things from what you posted:

  1. Your config resolution is fine (openclaw config get gateway.auth.token returns a value).
  2. You then did export OPENCLAW_GATEWAY_TOKEN="!MYTOKEN!" — that overrides what the CLI resolves from ~/.openclaw/.env.

If !MYTOKEN! is not exactly the token the running systemd gateway was started with, the gateway will immediately close the WS (and you’ll see exactly what you’re seeing).

Fix attempt (safe + fast)

A) Remove the override, then restart the gateway (systemd won’t pick up .env changes until restart)

unset OPENCLAW_GATEWAY_TOKEN
openclaw gateway restart
#

Then try:

openclaw devices list
openclaw cron status

(If you edited ~/.openclaw/.env at any point: restart is mandatory.)

B) If it still fails: rotate the gateway token (this is the “get unstuck” move)

This will break any existing UI sessions until you paste the new token.

openclaw config set gateway.auth.mode token
openclaw config set gateway.auth.token "$(openssl rand -hex 32)"
openclaw gateway restart

Getting the useful log lines without leaking secrets

#

Instead of tail, filter for auth/close reasons and paste only that output:

rg -n "AUTH_|TOKEN|PASSWORD|unauthor|PAIRING|required|device token|close\\s*\\(|websocket|handshake" /tmp/openclaw/openclaw-2026-03-13.log | tail -n 80

Before pasting, redact anything that looks like:

  • a token / password
  • any API keys (*_API_KEY, Authorization: Bearer ...)
  • long random strings

If you run the rg 
 | tail above, it’ll usually literally say AUTH_TOKEN_MISMATCH or similar, and we can zero in immediately.

exotic vine
#

Tried the following but still cant run openclaw devices list

openclaw config set gateway.auth.token "$(openssl rand -hex 32)"
openclaw gateway restart```
desert bobcatBOT
#

If rotating the token + openclaw gateway restart still doesn’t let any RPC command connect (devices list, cron status, etc.), we’re past “token missing” and into “gateway is closing the WS during/after handshake for some other reason”.

At this point the only thing that will tell us why is the gateway-side log, but you can share it safely by filtering.

1) First: confirm the gateway really restarted + is probing

Paste this (no secrets in it):

openclaw gateway status
openclaw gateway status --json

If gateway status --json exists (docs mention it), it often includes extra detail that helps.

2) Safest way to share logs (filtered)

Instead of tailing everything, run one of these and paste the output:

File log (recommended since your gateway status shows the path)

#
rg -n "AUTH_|unauthor|PAIRING|required|device|nonce|signature|token|password|handshake|close\\s*\\(|websocket|ERROR" \
  /tmp/openclaw/openclaw-2026-03-13.log | tail -n 120

Or systemd journal (sometimes cleaner)

journalctl --user -u openclaw-gateway -n 300 --no-pager | \
  rg -n "AUTH_|unauthor|PAIRING|required|device|nonce|signature|handshake|close\\s*\\(|websocket|ERROR" | tail -n 120

What to redact before pasting:

  • anything that looks like a token/password/key (long random strings)
  • any Authorization: header lines
  • provider keys (*_API_KEY, OPENROUTER_API_KEY, etc.)

3) One more common footgun: did .env change without a service restart?

#

If you edited ~/.openclaw/.env earlier: systemd won’t pick that up until restart. You already restarted, but just to be sure, run:

systemctl --user status openclaw-gateway --no-pager

(We’re looking for recent “Started 
” time and no crash loop.)


Once you paste the filtered log output, we’ll know if it’s:

  • AUTH_TOKEN_MISMATCH / AUTH_TOKEN_MISSING
  • PAIRING_REQUIRED
  • device nonce/signature issues
  • or an internal exception causing the gateway to drop the socket with code 1000.
exotic vine
#

I cant upload everything due to discord limit. journalctl mainly showed [ws] handshake timeout conn=STRING. Note that i had to remove a bit from --json due to discord limit

{
  "service": {
    "label": "systemd",
    "loaded": true,
    "loadedText": "enabled",
    "notLoadedText": "disabled",
    "command": {
      "programArguments": [
        "/usr/bin/node",
        "/home/fhorst/.npm-global/lib/node_modules/openclaw/dist/index.js",
        "gateway",
        "--port",
        "18789"
      ],
      "environment": {
        "OPENCLAW_GATEWAY_PORT": "18789"
      },
      },
      "sourcePath": "/home/fhorst/.config/systemd/user/openclaw-gateway.service"
    },
    "runtime": {
      "status": "running",
      "state": "active",
      "subState": "running",
      "pid": 13071,
      "lastExitStatus": 0,
      "lastExitReason": "0"
    },
    "configAudit": {
      "ok": true,
      "issues": []
    }
  },
  "config": {
    "cli": {
      "path": "/home/fhorst/.openclaw/openclaw.json",
      "exists": true,
      "valid": true,
      "controlUi": {
        "allowedOrigins": [
          "https://ocw.codehost.me"
        ]
      }
    },
    "daemon": {
      "path": "/home/fhorst/.openclaw/openclaw.json",
      "exists": true,
      "valid": true,
      "controlUi": {
        "allowedOrigins": [
          "https://ocw.codehost.me"
        ]
      }
    }
  },
  "gateway": {
    "bindMode": "loopback",
    "bindHost": "127.0.0.1",
    "port": 18789,
    "portSource": "service args",
    "probeUrl": "ws://127.0.0.1:18789",
    "probeNote": "Loopback-only gateway; only local clients can connect."
  },
  "port": {
    "port": 18789,
    "status": "busy",
    "listeners": [
      {
        "address": "127.0.0.1:18789",
        "pid": 13071,
        "command": "openclaw-gatewa",
        "commandLine": "openclaw-gateway",
        "user": "fhorst",
        "ppid": 190
      },
      {
      }
    ],
    ]
  },

desert bobcatBOT
#

[ws] handshake timeout is a big clue. That’s not “token mismatch” — it means the Gateway accepted a TCP connection but the WebSocket upgrade/initial connect never completed.

Given your gateway status --json shows:

controlUi.allowedOrigins: ["https://ocw.codehost.me"]
bindMode: "loopback"


I strongly suspect the Control UI origin allowlist is being enforced on the Gateway WS in a way that blocks non-browser clients (the CLI does not send an Origin header). If the gateway implementation “waits” instead of cleanly rejecting, you’ll see exactly what you’re seeing: handshake timeout in journal + “gateway closed (1000)” client-side.

Quick test (reversible)

Temporarily remove the origin allowlist and restart:

openclaw config unset gateway.controlUi.allowedOrigins
#
openclaw gateway restart
openclaw devices list

If devices list starts working immediately after that, we’ve found the culprit.

If you need remote UI at ocw.codehost.me

The recommended way is to keep the gateway on loopback and expose it via Tailscale Serve or an SSH tunnel, which avoids brittle origin config:

Docs: https://docs.openclaw.ai/web/control-ui (see the Tailnet access section)

If unsetting allowedOrigins does not fix it

Then we need 5–10 lines around the handshake timeout from journal (you can redact conn ids, tokens, etc.) — but try the allowedOrigins removal first; it matches your symptoms really well.

exotic vine
#

allowed origins did not fix it. I feel like reinstalling on a fresh machine and copying over the MEMORY.md, SOUL.md, etc files over is the best change i've got.

desert bobcatBOT
#

Reinstalling a whole new machine will work, but you can usually get the same “fresh start” effect by resetting just the local device-auth state (that’s exactly the class of issue your symptoms + the [ws] handshake timeout smell like).

There’s an existing bug pattern where the Gateway is fine, but the CLI gets stuck because the device identity / pairing state under ~/.openclaw/identity + ~/.openclaw/devices is borked (or stuck in a repair/pending state). Reinstalling “fixes” it because those files are new.

Try this first (safe if you backup, and reversible)

Do not paste the contents of these files — they can contain tokens.

  1. Stop the gateway:
openclaw gateway stop
  1. Backup the device/pairing state:
ts=$(date +%s)
cp -a ~/.openclaw/identity ~/.openclaw/identity.bak-$ts
#
cp -a ~/.openclaw/devices  ~/.openclaw/devices.bak-$ts
  1. Move aside the specific files that commonly cause this:
mv ~/.openclaw/identity/device-auth.json ~/.openclaw/identity/device-auth.json.bak-$ts 2>/dev/null || true
mv ~/.openclaw/devices/paired.json       ~/.openclaw/devices/paired.json.bak-$ts       2>/dev/null || true
mv ~/.openclaw/devices/pending.json      ~/.openclaw/devices/pending.json.bak-$ts      2>/dev/null || true
  1. Start the gateway again:
openclaw gateway start
  1. Retry:
#
openclaw devices list
openclaw cron status

On loopback (127.0.0.1) pairing should be auto-approved, so this should regenerate clean state and unblock the CLI.

If that still doesn’t fix it

Then I’d check for a binary mismatch (CLI and systemd service running different installs):

which openclaw
openclaw --version
node -v
openclaw gateway status --json


and at that point it’s probably worth a GitHub issue with the exact journalctl “handshake timeout” lines (redacting tokens). But I’d try the device-auth reset first — it’s the closest “fresh install” without actually moving machines.

exotic vine
#

Not even with pairing state, i still believe reinstalling is the best and easiest way to resolve this

desert bobcatBOT
#

Fair. If you’re at the “I’ve burned enough time” point, a fresh machine + selective copy is a totally reasonable path.

The key is: don’t copy the parts that are likely broken (device/pairing/identity state). Just bring over your workspace/personality/memory.

Easiest “clean reinstall but keep memory/persona”

  1. On the new machine: install + run onboarding so you have a working gateway/CLI baseline.
  2. Copy over only your workspace from the old machine.

By default that’s:

  • ~/.openclaw/workspace/ ← contains MEMORY.md, SOUL.md, USER.md, IDENTITY.md, TOOLS.md, memory/*.md, etc.

You can confirm the workspace path on the old machine with:

openclaw config get agents.defaults.workspace

Then copy that folder to the same path on the new machine (scp/rsync/tar).

#

Docs (official): https://docs.openclaw.ai/install/migrating
(That guide migrates everything; you’re basically doing the “copy workspace only” variant on purpose.)

If you also want to keep most state, but force device/pairing to regenerate

You can migrate ~/.openclaw/ but exclude these directories:

  • ~/.openclaw/identity/
  • ~/.openclaw/devices/

That preserves sessions/cron/channel creds, but forces re-pairing.

One ask (optional, but helpful)

This looks like a real bug edge-case (handshake timeout + CLI can’t do devices list). If you end up with 5 spare minutes after you’re unblocked, it’d be worth filing a GitHub issue with:

  • your OpenClaw version (2026.3.12)
  • OS/distro
  • the [ws] handshake timeout journal line(s)

Issues: https://github.com/openclaw/openclaw/issues