#Error: Config validation failed: channels.telegram.allowFrom: channels.telegram.dmPolicy="open" requ
1 messages · Page 1 of 1 (latest)
That validation is intentional: if you set channels.telegram.dmPolicy: "open", OpenClaw forces you to explicitly opt into “anyone can DM me” by requiring:
channels: {
telegram: {
dmPolicy: "open",
allowFrom: ["*"],
},
}
If you don’t want a public-facing Telegram bot, change the policy instead (recommended):
channels: {
telegram: {
dmPolicy: "pairing", // default-ish behavior, unknown users get pairing flow
// or: dmPolicy: "allowlist",
allowFrom: ["<your-telegram-user-id>"], // numeric id or @username
},
}
Docs reference: https://docs.openclaw.ai/channels/telegram#access-control-and-activation
Also: what does openclaw --version show?
2026.2.14. Now works but bot is not replying on Telegram evben thoug token is correct
/start doesnt work and not replying to messages
If config validates now but Telegram is silent, the fastest way to pinpoint it is: is the Gateway receiving updates at all, and is it allowed to answer in that chat?
Run these and paste the output (they’re safe):
openclaw gateway status
openclaw channels status --probe
openclaw logs --follow
Then while logs --follow is running, DM your Telegram bot something simple (e.g. ping). Check which bucket you fall into:
A) No inbound message shows up in logs
That’s a Telegram delivery problem, not OpenClaw logic. Common causes:
- You never clicked Start / sent a first DM to the bot (bots can’t message first).
- A webhook is set on that bot token (long-polling won’t receive updates), or another process is polling the same bot token (Bot API conflict).
B) Inbound message shows up, but no reply is sent
Then it’s usually:
- model failure (you’ll see “All models failed” / provider errors in logs)
- policy/activation gating (esp. if you’re talking in a group)
C) You’re testing in a Telegram group
By default groups often look “dead” because:
- mention is required (try mentioning the bot, or test in a DM first)
- BotFather privacy mode can hide messages unless mentioned/commanded (check
/setprivacy)
Docs ladder: https://docs.openclaw.ai/channels/troubleshooting (Telegram section)
If you paste the openclaw channels status --probe + the first Telegram-related error lines from the log tail, I can tell you exactly which one it is.
On Telegram, /start by itself won’t trigger an OpenClaw pairing code (and may look like “nothing happened”). Pairing codes are only sent when an unknown sender messages the bot while dmPolicy: "pairing" is enabled. Source: https://docs.openclaw.ai/help/faq#i-ran-start-in-telegram-but-didnt-get-a-pairing-code
Do this checklist (and please don’t paste your bot token here):
- Make sure you restarted after config changes
openclaw gateway restart
- Check if Telegram is connected + being polled
openclaw channels status --probe
openclaw logs --follow
While logs --follow is running, DM the bot a normal message like: hello
- If your
dmPolicyis pairing, check/approve:
openclaw pairing list telegram
# then approve the pending code if shown
- If the logs show no inbound updates at all, the most common Telegram gotcha is: a webhook is set (long-polling won’t receive anything) or another process is polling the same bot.
Check webhook (locally) and clear it:
curl -s "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/getWebhookInfo"
curl -s "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/deleteWebhook?drop_pending_updates=true"
openclaw gateway restart
If you paste the output of openclaw channels status --probe + the first Telegram-related error lines from openclaw logs --follow, I can tell you exactly which case it is.
That channels status line (“mode: polling … works”) only proves the bot token is valid + getMe succeeds — it doesn’t prove updates are flowing or that your DM is allowed.
Given (a) /start + messages get no reply and (b) pairing list telegram is empty, it’s almost always one of these:
1) Your DM policy is blocking you (allowlist/open mismatch)
Please paste these two outputs:
openclaw config get channels.telegram.dmPolicy
openclaw config get channels.telegram.allowFrom
If dmPolicy is "allowlist" and you’re not in allowFrom, OpenClaw will silently ignore you (no pairing request, no reply). Fix = add your Telegram from.id to allowFrom, or switch to pairing, or use open + allowFrom: ["*"].
Docs: https://docs.openclaw.ai/channels/telegram#access-control-and-activation
2) Telegram updates aren’t reaching OpenClaw (webhook or another poller)
Run (safe, doesn’t disrupt polling):
openclaw logs --follow
Then DM the bot “hello”. If no Telegram inbound update shows up in logs, check webhook state and clear it:
# replace with your real token locally; don’t paste it here
curl -s "https://api.telegram.org/bot<token>/getWebhookInfo"
curl -s "https://api.telegram.org/bot<token>/deleteWebhook?drop_pending_updates=true"
openclaw gateway restart
If another app/server is using the same bot token (another bot framework, another OpenClaw instance), Telegram will only deliver to one of them.
3) You’re testing in a group (not DM)
In groups, default behavior is often “looks dead” unless you mention the bot (or relax requireMention). DMs should reply without mention.
If you can paste the first ~30 lines around your Telegram message from openclaw logs --follow, I can tell you immediately which bucket you’re in (policy block vs no inbound updates vs send failure).
That Telegram JSON ({"ok":false,"error_code":404,"description":"Not Found"}) basically means your request didn’t hit a valid Bot API method for a valid token.
Two common causes:
- You accidentally called the base URL (or a typo), e.g.
.../bot<TOKEN>(no method) → 404 - The token you used in curl is wrong / has extra characters (quotes,
< >, whitespace/newline) → 404 even ongetMe
Run these exact checks (don’t paste your token here—just paste the JSON response):
curl -s "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/getMe"
curl -s "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/getWebhookInfo"
Interpretation:
- If
getMereturns 404 → the token you’re curling with is not valid (or not the same token OpenClaw is using).
- If
getMeis ok butgetWebhookInfoshows a non-emptyurl→ webhook is set, and OpenClaw polling won’t receive updates. Fix:
curl -s "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/deleteWebhook?drop_pending_updates=true"
openclaw gateway restart
Also, since pairing list telegram is empty, please paste:
openclaw config get channels.telegram.dmPolicy
openclaw config get channels.telegram.allowFrom
If dmPolicy is allowlist and you’re not in allowFrom, OpenClaw will ignore your DMs (no pairing request, no reply).
That {"ok":false,"error_code":404,"description":"Not Found"} from Telegram means the URL you called is not a valid Bot API endpoint for that token — in practice almost always:
- the token in the curl command is wrong / includes extra chars (common: you left the literal
<token>or included the< >brackets), or - you didn’t include the method (needs
/getMe,/getWebhookInfo, etc.)
Please sanity-check with getMe first (it’s the clearest signal):
# IMPORTANT: no < > brackets, no spaces, no extra quotes in the token
curl -s "https://api.telegram.org/botYOUR_TOKEN_HERE/getMe"
Expected: {"ok":true,"result":{...}}
If you still get 404 here → you’re not using a valid token in curl (or not the same token OpenClaw is using).
Once getMe is OK, then do webhook:
curl -s "https://api.telegram.org/botYOUR_TOKEN_HERE/getWebhookInfo"
- If it shows a non-empty
"url"→ clear it:
curl -s "https://api.telegram.org/botYOUR_TOKEN_HERE/deleteWebhook?drop_pending_updates=true"
openclaw gateway restart
If you’re unsure you’re curling the same token as OpenClaw: run locally (don’t paste here)
openclaw config get channels.telegram.botToken (or check your tokenFile) and use that exact string in the curl URL.
Nice — that output means the Telegram side is configured correctly:
- token is valid (
getMe ok) - webhook is not set (
url: "", and deleteWebhook says already deleted) - OpenClaw policy is wide open (
dmPolicy: "open",allowFrom: ["*"])
So the problem is now almost certainly either (1) OpenClaw is receiving updates but failing to generate/send replies, or (2) OpenClaw isn’t actually receiving updates (polling conflict).
1) Check what happens in logs when you DM the bot
Run:
openclaw logs --follow
Then DM @My_Bot a plain message like hello (not /start).
Now paste the first Telegram-related log block that appears after you send the message.
What I’m looking for:
- 409 Conflict / terminated by other getUpdates → you have another poller using the same bot token (another OpenClaw instance, a bot framework, etc.). Only one can poll. Kill/stop the other one.
- 403 Forbidden (often “bot was blocked by the user” or “can’t initiate conversation”) → unblock the bot in Telegram and hit Start again.
- All models failed / provider auth error → Telegram is fine; the model isn’t. (Then we fix models.)
2) Verify your models aren’t the real blocker
Also paste:
openclaw models status
If model auth is broken, OpenClaw can receive Telegram messages but never successfully produce a reply.
If you paste the Telegram log snippet + openclaw models status, I can tell you exactly which failure signature it is and the precise fix.
Cool — with dmPolicy: "open" + allowFrom: ["*"] + webhook cleared + getMe ok, the config/token side is fine.
The big clue in your getMe output is:
can_read_all_group_messages: false
That means BotFather privacy mode is ON. So:
- If you’re testing in a Telegram group/channel: the bot often won’t even receive normal messages (so nothing shows in logs) unless you mention it, send a command, or make it admin / disable privacy mode.
- Test in a 1:1 DM first (send plain text like
hello, not just/start).
Quick “are updates reaching this bot token?” test
Right after you send hello in a DM, run:
curl -s "https://api.telegram.org/botMYTOKEN/getUpdates?timeout=1&limit=5"
What it means:
- If you see your message in the JSON → Telegram is delivering updates, but OpenClaw is not consuming them (often: another OpenClaw instance not actually running Telegram polling, wrong gateway/service, or polling loop not running).
- If you get a 409 Conflict about
getUpdates→ something else is polling that bot token right now (could be OpenClaw, could be another bot process). Only one poller can win.
If you paste the result of that getUpdates call (redact token) and tell me DM vs group, I can tell you the exact next fix (mention/admin/privacy vs “another poller” vs “gateway not actually polling”).
getUpdates returning {"ok":true,"result":[]} right after you DM the bot means Telegram has no unconsumed updates for that token.
That can happen in two very different situations:
- Something is consuming updates already (OpenClaw or another poller), so your manual
getUpdatessees nothing. - Your “hello” didn’t actually reach the bot (less common, but then
getUpdatesalso stays empty).
Let’s make it deterministic.
A) Do a “catch it live” long‑poll test (best signal)
In Terminal A, run (no -s, longer timeout):
curl "https://api.telegram.org/botMYTOKEN/getUpdates?timeout=30&limit=1"
While that command is waiting, send a new DM to the bot: hello 123.
What you’ll see:
- If the curl returns an update containing your message → Telegram delivery is fine, and OpenClaw is not polling that token (or is using a different token/config).
- If the curl returns a 409 Conflict (
terminated by other getUpdates request) → another poller is active (often the OpenClaw gateway) and you can’tgetUpdatesconcurrently. - If it times out with no result repeatedly → your DM is not arriving at the Bot API (then we focus on Telegram/client-side oddities, but usually this means you’re not actually messaging the same bot/token).
B) Verify the Gateway service is using the config you’re editing
Paste the output of:
openclaw gateway status
Specifically, I’m looking for whether Config (cli) and Config (service) differ. If they differ, the daemon is running with a different config than the one you’re editing, and that would explain “no inbound, no logs”.
C) Grab Telegram-specific logs (since openclaw logs --follow showed only heartbeat)
Try:
If you DM the bot and nothing shows up in OpenClaw logs, and getUpdates stays empty, we need to answer one question first:
Is Telegram delivering any updates for that bot token, or is something else consuming them?
1) Run a blocking getUpdates (this removes timing ambiguity)
In Terminal A:
curl "https://api.telegram.org/botMYTOKEN/getUpdates?timeout=30&limit=1&allowed_updates=%5B%22message%22%5D"
While that command is sitting there, send a new DM to the bot from Telegram: hello 123.
Outcomes:
- You get an update JSON with your “hello 123” → Telegram delivery is fine, but OpenClaw is not polling / not using this token at runtime.
- You get a 409 conflict → something is already polling this bot token (could be OpenClaw, could be another bot process).
- It just returns
result: []after waiting → your DM is not reaching the Bot API (most often: you’re not actually DM’ing this bot, or you’re testing in a group where privacy mode hides unmentioned messages).
2) Check for the classic “CLI config vs service config” mismatch
Paste the output of:
openclaw gateway status
Look specifically for Config (cli) vs Config (service). If they differ, you’re editing one config but the running daemon is using another.
3) Use channel-filtered logs (gateway logs can be quiet)
Try:
openclaw channels logs --channel telegram
(If it errors, run openclaw channels logs --help and paste that.)
Reply with what happens in step (1) + the gateway status output and we’ll know exactly which branch this is.
openclaw logs --limit 500 | grep -iE "telegram|grammy|getUpdates|update|poll|409|forbidden"
Paste what that prints (and please redact any keys/tokens).
Once you tell me what the long‑poll test does (update vs 409 vs nothing) + openclaw gateway status, we’ll know exactly which branch we’re in.
Perfect — that getUpdates response proves Telegram is delivering your DM to the Bot API.
It also proves something else: OpenClaw is not consuming updates for that bot token (otherwise your getUpdates would usually be empty or you’d hit a 409 conflict).
So this is now a Gateway runtime issue (wrong config/state, wrong service, or Telegram poller not running), not a Telegram/token/policy issue.
1) Check for “CLI config vs service config” mismatch (most common cause)
Run and paste:
openclaw gateway status
If it shows Config (service) is not the same file as your ~/.openclaw/openclaw.json, then you’re editing one config but the daemon is running another (often: service installed under a different user / different state dir). Fix is usually:
openclaw doctor
openclaw gateway restart
2) Confirm whether the running Gateway thinks Telegram is active
Paste:
openclaw status --deep
(That one queries the running gateway and does live channel probes.)
Important while testing
Don’t keep using curl getUpdates in the background while trying to make OpenClaw reply — it can steal updates or cause getUpdates conflicts/backoff.
Two separate things here:
-
No pairing codes is expected right now
You havechannels.telegram.dmPolicy = "open"+allowFrom = ["*"], so there is no pairing flow. Pairing codes only happen withdmPolicy: "pairing". -
The important part: your
getUpdatesproves Telegram is receiving your DM, but OpenClaw isn’t polling/handling it
You got the DM back via:
curl .../getUpdates?timeout=30...
# result contained "Hello 123"
If the OpenClaw gateway were actually polling that bot token, you’d typically see either:
- a 409 conflict when you try
getUpdates, or - the update gets consumed and your manual
getUpdatesstays empty.
Send openclaw gateway status output and we’ll know immediately if this is a service/config-path mismatch.
So next we need to confirm the gateway service is running with the config you think it is, and whether Telegram polling started (or crashed).
Please run and paste these outputs:
openclaw gateway status
openclaw logs --limit 300 | grep -iE "telegram|getUpdates|grammy|conflict|poll"
What I’m looking for in gateway status:
- Config (cli) vs Config (service) mismatch → daemon is using a different config/home/user, so Telegram never starts.
If they do mismatch, the usual fix is:
openclaw doctor
openclaw gateway restart
(and if Doctor says the service entrypoint/config is wrong, let it repair it).
Once you paste openclaw gateway status, we can tell immediately if this is the config/service mismatch case.
That gateway closed (1008): unauthorized: device token mismatch is almost always your CLI has a stale device token cached locally (gateway/service got reinstalled, state dir changed, token rotated, etc.). Fix is to clear the CLI’s cached device auth so it can re-issue a fresh one.
1) Clear the cached device token (safe: rename to .bak)
On the machine where you run openclaw:
# Default state dir (new)
ls -la ~/.openclaw/identity || true
# Legacy state dir (older installs)
ls -la ~/.clawdbot/identity || true
Then rename the auth file if it exists:
mv ~/.openclaw/identity/device-auth.json ~/.openclaw/identity/device-auth.json.bak 2>/dev/null || true
mv ~/.clawdbot/identity/device-auth.json ~/.clawdbot/identity/device-auth.json.bak 2>/dev/null || true
(Do not touch your Telegram token/config; this is just local CLI↔gateway device auth.)
2) Restart the gateway + re-check status
openclaw gateway restart
openclaw gateway status
If it now says something like pairing required / pending device approval, run:
openclaw devices list
…and approve the pending request.
3) Then re-test Telegram (important)
When testing Telegram, don’t run curl getUpdates in parallel, because that will consume the updates before OpenClaw can see them.
After the gateway auth is fixed:
openclaw logs --follow | grep -i telegram
DM the bot “hello” and you should finally see Telegram poller activity + a reply.
If you paste the new openclaw gateway status output (redact any tokens), I can tell you which of the two identity dirs you’re actually running under and whether there’s still a CLI/service state mismatch.
That’s progress: starting provider (@My_Bot) means the Gateway is now actually loading the Telegram channel and talking to Telegram.
The new error is separate:
What BOT_COMMANDS_TOO_MUCH means
Telegram rejected OpenClaw’s setMyCommands call because it thinks the bot is trying to register too many menu commands (Telegram has strict limits). This only affects the Telegram command menu — it shouldn’t be required for normal DM replies, but it’s noisy and can hint you have a lot of commands enabled (often from skill/plugin command registration).
Quick fix (recommended): stop registering skill commands in Telegram’s menu
This keeps the bot working but reduces the command list drastically:
openclaw config set channels.telegram.commands.nativeSkills false --json
openclaw gateway restart
If you don’t care about Telegram’s command menu at all, nuke native menu commands entirely:
openclaw config set channels.telegram.commands.native false --json
openclaw gateway restart
Then re-test DMs (important)
- Don’t run
curl getUpdateswhile testing (it “steals” updates from OpenClaw). - Run:
openclaw logs --follow --max-bytes 1000000 --plain | grep -iE "telegram|getUpdates|conflict|unauthorized|skip"
- DM the bot plain text like:
hello(not/start) and see what it logs.
If it still doesn’t reply, paste the first ~30 log lines after you send the DM (the “skip reason” line is usually the key).
That log explains both problems, and they’re unrelated:
- Your CLI can’t stay connected to the Gateway
This line is the real blocker foropenclaw logs --follow/gateway statusetc:
unauthorized ... reason=device_token_mismatch
That’s the CLI presenting a stale cached device token to the gateway.
Fix (safe: rename to .bak):
# new state dir
mv ~/.openclaw/identity/device-auth.json ~/.openclaw/identity/device-auth.json.bak 2>/dev/null || true
# legacy state dir (in case you’re on older state)
mv ~/.clawdbot/identity/device-auth.json ~/.clawdbot/identity/device-auth.json.bak 2>/dev/null || true
Then:
openclaw gateway restart
openclaw gateway status
If it then shows a pending device approval:
openclaw devices list
openclaw devices approve <requestId>
- Telegram error:
BOT_COMMANDS_TOO_MUCH
This is Telegram rejecting the command menu registration (setMyCommands) because too many commands are being registered.
Quick workaround (reduce command count hard):
openclaw config set channels.telegram.commands.nativeSkills false --json
openclaw gateway restart
(or disable Telegram native menu commands entirely:)
openclaw config set channels.telegram.commands.native false --json
openclaw gateway restart
After you do (1) and can follow logs reliably again, DM the bot “hello” (and don’t run curl getUpdates at the same time) and we can see the real “why didn’t it reply” lines.
Those unauthorized … reason=device_token_mismatch lines are not Telegram — that’s just your CLI failing to authenticate to the running Gateway, so openclaw logs --follow can’t work until you clear/re-issue the CLI device token.
Fix the CLI ↔ Gateway device token mismatch (safe, no deletes)
Run this to find which state dir you’re actually using and rename the cached token:
find ~ -maxdepth 4 -path '*/identity/device-auth.json' -print
# then for each path it prints, rename it:
mv /path/to/identity/device-auth.json /path/to/identity/device-auth.json.bak
Then restart and re-try:
openclaw gateway restart
openclaw gateway status
openclaw logs --follow
If it still says device_token_mismatch, also rename the device identity (forces a fresh deviceId + fresh token issuance):
find ~ -maxdepth 4 -path '*/identity/device.json' -print
mv /path/to/identity/device.json /path/to/identity/device.json.bak
openclaw gateway restart
Telegram command menu error
Good news: after you set channels.telegram.commands.nativeSkills=false, I no longer see the setMyCommands … BOT_COMMANDS_TOO_MUCH line in the later snippet — so that part may already be fixed.
If you need Telegram logs before CLI auth is fixed
You can tail the gateway file log directly (no RPC/device auth involved):
ls -t /tmp/openclaw/openclaw-*.log | head -1
tail -f /tmp/openclaw/openclaw-YYYY-MM-DD.log | grep -i telegram
After the device-token fix, DM the bot “hello” once and paste the first Telegram-related lines that appear right after.
Yep — that behavior makes sense: clearing only device-auth.json isn’t enough if the gateway already has a paired record for your existing deviceId.
In that case, when the CLI reconnects with the same deviceId (from device.json) but no longer has the matching device token, the gateway rejects it as device_token_mismatch.
Fix: reset the CLI device identity too (forces a new deviceId)
Run:
ls -la ~/.openclaw/identity
# move the identity keypair/fingerprint (this is what keeps the same deviceId)
mv ~/.openclaw/identity/device.json ~/.openclaw/identity/device.json.bak 2>/dev/null || true
# and make sure the auth cache is gone too
mv ~/.openclaw/identity/device-auth.json ~/.openclaw/identity/device-auth.json.bak 2>/dev/null || true
openclaw gateway restart
openclaw gateway status
If you have any legacy state dir, do the same there too:
mv ~/.clawdbot/identity/device.json ~/.clawdbot/identity/device.json.bak 2>/dev/null || true
mv ~/.clawdbot/identity/device-auth.json ~/.clawdbot/identity/device-auth.json.bak 2>/dev/null || true
If it still fails
Paste:
find ~ -maxdepth 4 -path '*/identity/device*.json' -print
(because it means the CLI is still finding another identity file somewhere and reusing the old deviceId)
Once gateway status works again, we can go back to Telegram DM replies (and you can reliably openclaw logs --follow without the auth disconnect spam).
You accidentally ran the placeholder command (/path/to/...). Use the actual path from your find output.
Since the gateway is still rejecting with device_token_mismatch, you need to clear both the cached device token and the device identity (so the CLI gets a new deviceId and the gateway auto-approves it as “local”).
Run:
mv /home/kazimieras/.openclaw/identity/device-auth.json /home/kazimieras/.openclaw/identity/device-auth.json.bak 2>/dev/null || true
mv /home/kazimieras/.openclaw/identity/device.json /home/kazimieras/.openclaw/identity/device.json.bak 2>/dev/null || true
openclaw gateway restart
openclaw gateway status
If it still says device_token_mismatch after that, it means there’s another identity dir being used somewhere (different $HOME, sudo, or OPENCLAW_STATE_DIR). Then paste:
find ~ -maxdepth 6 -path '*/identity/device*.json' -print
env | grep -i openclaw
You’re good — I’m just asking you to run two quick commands so we can see why the gateway thinks your device token is wrong (often it’s an env/state-dir mismatch).
Run these on the gateway machine and paste the output (safe; no tokens):
- Env overrides (often the culprit)
env | grep -Ei 'OPENCLAW|CLAWDBOT' || true
- Your deviceId (safe to share)
jq -r '.deviceId' ~/.openclaw/identity/device.json 2>/dev/null || \
grep -oP '"deviceId"\\s*:\\s*"\\K[^"]+' ~/.openclaw/identity/device.json
Optional (don’t paste file contents, just filenames):
ls -la ~/.openclaw/identity | egrep 'device(-auth)?\\.json' || true
Note: I’m not asking you to paste find ~ ... output here (too easy to leak private paths). If those 2 outputs look normal but it still mismatches, we’ll do the “backup device.json + device-auth.json and restart gateway” fix next.
Nice — that narrows it down a lot:
- No OPENCLAW/CLAWDBOT env overrides in your shell âś…
- Your deviceId is
d6366ec0cb4d...14a33bacâś… - But your
ls | egrep 'device(-auth)?\.json'printed nothing, which is weird because you did read~/.openclaw/identity/device.json.
Next, let’s confirm what’s actually on disk + whether the gateway has you paired.
1) Show what’s in the identity dir (paste output)
ls -la ~/.openclaw/identity
2) Confirm the device.json file exists + perms (paste output)
stat ~/.openclaw/identity/device.json
3) Check if the gateway has a paired-devices store (paste output)
ls -la ~/.openclaw/devices
4) Check if that specific deviceId is paired (paste output: just true/false)
ID="d6366ec0cb4dfb5302a6932c68fc1fc93c2c8d3b80cdefe34ebb952514a33bac"
jq -r --arg id "$ID" 'has($id)' ~/.openclaw/devices/paired.json 2>/dev/null || echo "no-jq-or-no-file"
5) Paste the gateway’s last unauthorized reason from logs (safe; no secrets)
LOG="$(ls -t /tmp/openclaw*/openclaw-*.log 2>/dev/null | head -1)"
echo "$LOG"
tail -n 300 "$LOG" | egrep -i 'unauthorized conn=|device identity|required|pairing required|token_missing|token_mismatch' | tail -50
Why these matter:
- If
paired.jsondoesn’t exist (or doesn’t contain your deviceId), the gateway may never be issuing/storing a device token for you. - If the log shows
reason=token_mismatch, then the gateway is rejecting whatever token the CLI is presenting (either the gateway auth token or a device token).
Once you paste 1–5, I can tell you the exact minimal fix (usually either “paired.json missing / perms wrong” or “CLI is using a different token than the service”).
Good — your gateway has you paired (has(deviceId) == true). So this isn’t “not paired”; it’s almost always a stale device token cached in identity/device-auth.json (or your CLI is using the wrong shared token).
Step 1 (fastest): force a fresh device token
This does not require editing config or deleting pairing; it just forces the CLI to stop using the cached device-token and fall back to the shared gateway token once, which will re-issue/store a fresh device token on success.
mv ~/.openclaw/identity/device-auth.json ~/.openclaw/identity/device-auth.json.bad.$(date +%s)
openclaw gateway status
- If that works: you’re unstuck.
device-auth.jsonwill be recreated automatically on next connect.
If it STILL says unauthorized after that
Then the shared token the CLI is using doesn’t match what the gateway expects. Safest sync (no pasting secrets) is:
openclaw config set gateway.remote.token "$(openclaw config get gateway.auth.token)"
openclaw gateway restart
openclaw gateway status
(That copies the value locally; don’t paste the token output in Discord.)
If either step fails
Paste only the single-line error from openclaw gateway status and (optional but super helpful) the gateway log line:
LOG="$(ls -t /tmp/openclaw*/openclaw-*.log 2>/dev/null | head -1)"
tail -n 200 "$LOG" | egrep -i 'unauthorized conn=|token_mismatch|token_missing' | tail -20
That line will tell us whether it’s gateway token mismatch/missing vs something else.
That output actually tells us two separate things:
-
The gateway is already running on
127.0.0.1:18789(pid 38650)
→ so don’t runopenclaw gateway(that’s why you get “Port 18789 is already in use”). Useopenclaw gateway status/openclaw logsetc. -
The CLI is failing with device token mismatch because it’s trying to auth with the cached device token from
~/.openclaw/identity/device-auth.json, and it can’t fall back unless you also provide the shared gateway token.
Fix (recommended): run status once with the shared gateway token
This will allow the CLI to fall back, clear the bad device token, and the gateway will re-issue a fresh device token.
openclaw gateway status --url ws://127.0.0.1:18789 --token "$(openclaw config get gateway.auth.token)"
After that, try again without --token:
openclaw gateway status --url ws://127.0.0.1:18789
If it still complains: hard-clear the cached device token
mv ~/.openclaw/identity/device-auth.json ~/.openclaw/identity/device-auth.json.bad.$(date +%s)
openclaw gateway status --url ws://127.0.0.1:18789 --token "$(openclaw config get gateway.auth.token)"
(Do not paste the token; the command substitution keeps it local.)
Tell me which of the two commands you ran and whether gateway status now shows RPC probe: ok (or still fails), and we’ll finish the Telegram DM test after.
still the same
If it’s “still the same”, it’s almost certainly because the CLI is still preferring the cached device token in ~/.openclaw/identity/device-auth.json (even when you pass --token). The client code does:
use stored device-auth token first; only if connect fails and then you retry will it fall back.
So let’s force it cleanly.
Do this exactly (and then retry once)
mv ~/.openclaw/identity/device-auth.json ~/.openclaw/identity/device-auth.json.bad.$(date +%s)
openclaw gateway status --url ws://127.0.0.1:18789 --token "$(openclaw config get gateway.auth.token)"
Then immediately:
openclaw gateway status --url ws://127.0.0.1:18789
If you STILL get “device token mismatch” after that
Then the running gateway is not using the same shared token that openclaw config get gateway.auth.token is showing (common when the service has an env var token, or was started with different config).
Please paste these (safe; no secrets):
- Confirm device-auth really got moved:
ls -la ~/.openclaw/identity/device-auth.json*
- Show how the gateway process was launched:
ps -p 38650 -o user=,args=
- Show the gateway’s own “unauthorized … reason=…” line from logs:
LOG="$(ls -t /tmp/openclaw*/openclaw-*.log 2>/dev/null | head -1)"
tail -n 300 "$LOG" | egrep -i 'unauthorized conn=|reason=token_|reason=device|device-auth' | tail -30
With those three, I can tell you whether it’s a shared gateway token mismatch (service env/config mismatch) or an actual device-token scope/rotation issue.
You’ve got two separate things going on here:
1) Config validation: telegram.dmPolicy="open" requires allowFrom to include "*"
That error is expected/intentional: “open” means public DMs, so OpenClaw forces you to explicitly opt in by having "*" in channels.telegram.allowFrom.
If you don’t want a public Telegram bot (recommended)
Use pairing (default) or allowlist, and do not include "*":
channels: {
telegram: {
dmPolicy: "allowlist", // or "pairing"
allowFrom: ["<your_telegram_user_id>"],
}
}
Docs: https://docs.openclaw.ai/channels/telegram#access-control-dms--groups
FAQ bit: https://docs.openclaw.ai/help/faq#telegram-what-goes-in-allowfrom
If you do want it public
channels: {
telegram: {
dmPolicy: "open",
allowFrom: ["*"],
}
}
(Adding "*" effectively overrides any other IDs.)
2) Gateway auth: unauthorized: device token mismatch
This usually happens when the CLI is not talking to the same profile/state/config that the running gateway service is using, or the gateway is running with a different token than the one you’re passing.
Please run these and paste output (they redact sensitive bits)
openclaw --version
openclaw status --all
openclaw gateway status --deep
What I’m looking for:
Config (cli)vsConfig (service)mismatch (super common)- which state dir/profile the service is actually using
- whether the gateway is expecting token vs password, and from where
If you do see Config (cli) and Config (service) differ, the usual fix is: