#Telegram webhook fails to register — gateway cannot reach Telegram API

1 messages · Page 1 of 1 (latest)

lime silo
#

Symptoms:

Webhook URL shows null in Telegram API (getWebhookInfo)
~14-17 second message delays (polling mode fallback)
Ngrok tunnel is healthy and responding (returns 401 for unauthorized requests as expected)
Manual curl to Telegram API from host shell works fine
OpenClaw gateway fails with network errors
Logs showing the problem:

Copy
{"subsystem":"telegram/network"}: fetch fallback: enabling sticky IPv4-only dispatcher (codes=ETIMEDOUT,ENETUNREACH)
{"subsystem":"gateway/channels/telegram"}: telegram setWebhook failed: Network request for 'setWebhook' failed!
Environment:

OpenClaw version: 2026.4.25 (aa36ee6)
Gateway mode: webhook configured with ngrok (https://undecocted-kathleen-snowy.ngrok-free.dev/telegram-webhook)
Config has webhookUrl and webhookSecret set correctly
Ngrok tunnel: Running and healthy (port 8787 → 127.0.0.1:8787)
What works:

Ngrok tunnel responds correctly (HTTP 401 for unauthorized webhook requests)
Manual curl https://api.telegram.org/bot<token>/setWebhook from host succeeds
Polling mode works (messages deliver, just slowly)
What doesn't work:

OpenClaw gateway cannot reach api.telegram.org to register webhook
IPv6 appears to fail, IPv4 fallback not resolving properly
Gateway logs show ETIMEDOUT/ENETUNREACH errors
Expected behavior: Gateway should successfully call Telegram API to register webhook URL.

Current workaround: Polling mode with ~14-17s delay.

floral eagleBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

brave solarBOT
#

This looks like gateway outbound egress to api.telegram.org, not an ngrok/webhook-listener problem. The 401 from ngrok is actually a good sign: the local webhook path is reachable, but OpenClaw can’t complete the outbound setWebhook call.

The first thing I’d try is forcing Telegram’s Node/undici path to IPv4 in OpenClaw config, then restart the gateway:

{
  channels: {
    telegram: {
      network: {
        autoSelectFamily: false,
        dnsResultOrder: "ipv4first",
      },
    },
  },
}
#

Then:

openclaw gateway restart
openclaw logs --follow

That fetch fallback: enabling sticky IPv4-only dispatcher line means OpenClaw already detected a Telegram network failure and tried its IPv4 fallback, but since setWebhook still failed, either the IPv4 retry is also timing out or the gateway service environment differs from your shell.

A couple useful checks:

openclaw status --all
openclaw gateway status

And if you’re running the gateway as a service, don’t rely on shell env vars for this test — put the network override in config so the service definitely sees it.

lime silo
#

ssue: Telegram webhook registration fails despite ipv4first network config

What we tried:

Added to ~/.openclaw/openclaw.json:
Gateway restarted at 21:17:54
Config confirmed in place before restart
Result:

❌ setWebhook still fails at 21:20:10: "Network request for 'setWebhook' failed!"
❌ Webhook URL stays null in Telegram API
❌ Telegram channel broken — no incoming messages
✅ Outgoing messages work (via API calls)
✅ Control UI works (only way to communicate)
Current state:

Gateway can't reach api.telegram.org to register webhook
IPv6 errors persist despite ipv4first setting
No "sticky IPv4-only dispatcher" log lines seen after restart
Need: Either config path is wrong for this version, or need alternative method to force IPv4 for Telegram API calls.

Messages via Telegram are NOT reaching me — only Control UI works.

brave solarBOT
#

That config key is real for 2026.4.25, so this is probably one of two things:

  1. The running account isn’t getting that network config — common with channels.telegram.accounts.*
  2. setWebhook is failing on a different path than normal sends, which is bug-worthy since sendMessage works

For the account case, put the network override on the same Telegram account that has the token/webhook:

{
  channels: {
    telegram: {
      enabled: true,
      accounts: {
        default: {
          botToken: "...",
          webhookUrl: "https://undecocted-kathleen-snowy.ngrok-free.dev/telegram-webhook",
#
          webhookSecret: "...",
          network: {
            autoSelectFamily: false,
            dnsResultOrder: "ipv4first",
          },
        },
      },
    },
  },
}

If you’re not using accounts, top-level is fine:

#
{
  channels: {
    telegram: {
      network: {
        autoSelectFamily: false,
        dnsResultOrder: "ipv4first",
      },
    },
  },
}

For a stronger one-shot test, stop the service and run foreground with env overrides:

#
openclaw gateway stop

OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1 \
OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first \
OPENCLAW_LOG_LEVEL=debug \
openclaw gateway

Then look for:

autoSelectFamily=false
dnsResultOrder=ipv4first
telegram setWebhook failed
lime silo
#

21:42:02 [gateway] loading configuration…
21:42:03 [gateway] resolving authentication…
21:42:03 [gateway] starting...
21:42:06
21:42:15 [gateway] [plugins] ignored plugins.load.paths entry that points at OpenClaw's current bundled plugin directory; remove this redundant path or run openclaw doctor --fix (source=/home/sysadmin/.nvm/versions/node/v24.14.1/lib/node_modules/openclaw/dist/extensions/tokenjuice)
21:42:15 [gateway] [plugins] providerAuthEnvVars is deprecated compatibility metadata for provider env-var lookup; mirror meshy env vars to setup.providers[].envVars before the deprecation window closes (plugin=meshy-image-provider, source=/home/sysadmin/.openclaw/extensions/meshy-image-provider/openclaw.plugin.json)
21:42:15 [gateway] starting HTTP server...
21:42:15 [canvas] host mounted at http://0.0.0.0:18790/__openclaw__/canvas/ (root /home/sysadmin/.openclaw/canvas)
21:42:15 [gateway] ⚠️ Gateway is binding to a non-loopback address. Ensure authentication is configured before exposing to public networks.
21:42:15 [health-monitor] started (interval: 300s, startup-grace: 60s, channel-connect-grace: 120s)
21:42:15 [gateway] agent model: ollama/kimi-k2.6:cloud
21:42:15 [gateway] ready (7 plugins: browser, discord, memory-core, memory-wiki, openclaw-web-search, telegram, tokenjuice; 11.5s)
21:42:15 [gateway] log file: /tmp/openclaw/openclaw-2026-04-27.log
21:42:15 [gateway] security warning: dangerous config flags enabled: gateway.controlUi.allowInsecureAuth=true, gateway.controlUi.dangerouslyDisableDeviceAuth=true. Run openclaw security audit.
21:42:15 [gateway] starting channels and sidecars...
21:42:15 [hooks] loaded 4 internal hook handlers

brave solarBOT
#

I don’t see the actual config snippet in the paste, and the log stops right before Telegram starts (starting channels and sidecars...). So the next useful thing is the file log, not the console excerpt.

Please grab the Telegram lines from the log file it printed:

grep -Ei 'telegram|autoSelectFamily|dnsResultOrder|setWebhook|ENETUNREACH|ETIMEDOUT|fetch failed' \
  /tmp/openclaw/openclaw-2026-04-27.log | tail -120

Also, one thing stands out: you’re running from nvm Node 24:

/home/sysadmin/.nvm/versions/node/v24.14.1/...

That’s supported, but nvm environments can differ from your shell/network setup. For the strongest foreground test, run:

#
openclaw gateway stop

NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt \
OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1 \
OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first \
OPENCLAW_LOG_LEVEL=debug \
openclaw gateway

Then confirm the log contains:

autoSelectFamily=false
dnsResultOrder=ipv4first
#

If those lines don’t appear, the Telegram transport is not seeing the override/config. If they do appear and setWebhook still fails while sendMessage works, that’s likely a webhook registration bug/path-specific transport issue.

Temporary recovery: remove/comment webhookUrl + webhookSecret and restart so Telegram falls back to polling again.

Docs: https://docs.openclaw.ai/channels/telegram

lime silo
#

21:42:29 [ws] webchat connected conn=dd1bdea3-4db3-4d12-a715-a86c55b6bde4 remote=192.168.7.138 client=openclaw-control-ui webchat v2026.4.25
21:42:47
21:42:48 [browser/server] Browser control listening on http://127.0.0.1:18792/ (auth=token)
21:42:48 [heartbeat] started
21:42:48 [ws] ⇄ res ✓ sessions.list 62ms conn=dd1bdea3…bde4 id=79485d08…d88f
21:42:48 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-agent resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-agent
21:42:48 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-generation resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-generation
21:42:48 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-printing resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-printing
21:42:48 [ws] ⇄ res ✓ commands.list 188ms conn=dd1bdea3…bde4 id=6c40a7e5…1371
21:42:59 [ws] ⇄ res ✓ models.list 11446ms conn=dd1bdea3…bde4 id=69c9f13c…d7a5
21:42:59 [telegram] [default] starting provider
21:42:59 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-agent resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-agent
21:42:59 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-generation resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-generation

brave solarBOT
#

This snippet helps: Telegram is only at:

[telegram] [default] starting provider

The pasted part doesn’t include the actual webhook attempt yet. The skill symlink warnings are unrelated noise.

Two important reads:

  • Active Telegram account is default.
  • If webhook startup succeeds, you should later see lines like webhook local listener... / webhook advertised.... If you never see those, it’s failing during Telegram startup before/at setWebhook.

Please paste the next Telegram-only chunk:

#
grep -Ei 'telegram|autoSelectFamily|dnsResultOrder|setWebhook|webhook local|webhook advertised|ENETUNREACH|ETIMEDOUT|fetch failed' \
  /tmp/openclaw/openclaw-2026-04-27.log | tail -200

Also quick Node-vs-curl check from the same shell you start foreground OpenClaw in:

node -e "fetch('https://api.telegram.org').then(r=>console.log('status', r.status)).catch(e=>{console.error(e); console.error('cause=', e.cause)})"

If curl works but this Node fetch fails, it’s not the webhook config — it’s Node/undici egress/TLS/DNS.

To restore Telegram while debugging, comment/remove:

#
webhookUrl
webhookSecret

then restart; that forces polling instead of aborting webhook startup.

lime silo
#

21:42:48 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-printing resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-printing
21:42:48 [ws] ⇄ res ✓ commands.list 188ms conn=dd1bdea3…bde4 id=6c40a7e5…1371
21:42:59 [ws] ⇄ res ✓ models.list 11446ms conn=dd1bdea3…bde4 id=69c9f13c…d7a5
21:42:59 [telegram] [default] starting provider
21:42:59 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-agent resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-agent
21:42:59 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-generation resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-generation
21:42:59 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-printing resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-printing
21:42:59 [telegram] menu text exceeded the conservative 5700-character payload budget; shortening descriptions to keep 63 commands visible.
21:42:59 [discord] [default] starting provider
21:42:59 [ws] ⇄ res ✓ node.list 11871ms conn=dd1bdea3…bde4 id=05f804bb…ece5
21:42:59 [ws] ⇄ res ✓ device.pair.list 11873ms conn=dd1bdea3…bde4 id=35d07d3e…d5ab
21:43:07
21:44:12 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-agent resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-agent

#

21:44:12 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-generation resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-generation
21:44:12 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-printing resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-printing
21:44:14 [telegram] deleteMyCommands failed: Network request for 'deleteMyCommands' failed!
21:44:18 [discord] logged in to discord as 1490034267533738074 (TaskMaster)
21:44:18 [telegram] webhook local listener on http://127.0.0.1:8787/telegram-webhook
21:44:18 [telegram] webhook advertised to telegram on https://undecocted-kathleen-snowy.ngrok-free.dev/telegram-webhook
21:44:20 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-agent resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-agent
21:44:20 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-generation resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-generation
21:44:20 [skills] Skipping escaped skill path outside its configured root: source=openclaw-workspace root=~/.openclaw/workspace/skills reason=symlink-escape requested=~/.openclaw/workspace/skills/meshy-3d-printing resolved=~/.openclaw/workspace/.agents/skills/meshy-3d-printing
21:44:22
21:44:22 [plugins] memory-core: managed dreaming cron could not be reconciled (cron service unavailable).
21:44:30
21:44:30 [ws] ⇄ res ✓ node.list 72ms conn=dd1bdea3…bde4 id=0829d49d…9764

#

21:44:50 [tools] tools.allow allowlist contains unknown entries (mempalace_add_drawer, mempalace_diary_write, mempalace_search, mempalace_status, mempalace_list_wings, mempalace_list_rooms, mempalace_get_taxonomy, mempalace_kg_query, mempalace_kg_add, mempalace_kg_invalidate, mempalace_kg_timeline, mempalace_kg_stats, mempalace_traverse, mempalace_find_tunnels, mempalace_graph_stats, mempalace_delete_drawer, mempalace_diary_read). These entries won't match any tool unless the plugin is enabled.
21:44:50 [bundle-mcp] server "mempalace": env "PYTHONPATH" is blocked for stdio startup safety and was ignored.
21:44:51 [agent/embedded] tools: tools.allow allowlist contains unknown entries (ollama_web_search, ollama_web_fetch, mempalace_add_drawer, mempalace_diary_write, mempalace_search, mempalace_status, mempalace_list_wings, mempalace_list_rooms, mempalace_get_taxonomy, mempalace_kg_query, mempalace_kg_add, mempalace_kg_invalidate, mempalace_kg_timeline, mempalace_kg_stats, mempalace_traverse, mempalace_find_tunnels, mempalace_graph_stats, mempalace_delete_drawer, mempalace_diary_read). These entries won't match any tool unless the plugin is enabled.

brave solarBOT
#

That log is useful — Telegram is getting past “provider start”, but it is not reaching successful webhook startup.

Expected success lines would be:

webhook local listener on http://...
webhook advertised to telegram on https://...

Since those never appear, it’s almost certainly stuck/failing before or during setWebhook.

One thing I’d do now: force a short Telegram API timeout and disable native command menu sync for one restart, just to remove setMyCommands noise from the startup path:

{
  channels: {
#
    telegram: {
      timeoutSeconds: 10,
      commands: {
        native: false,
      },
      network: {
        autoSelectFamily: false,
        dnsResultOrder: "ipv4first",
      },
    },
  },
}

If you’re using channels.telegram.accounts.default, put those under accounts.default instead.

#

Then restart and grep only Telegram:

openclaw gateway restart

grep -Ei 'telegram|autoSelectFamily|dnsResultOrder|setWebhook|setMyCommands|webhook local|webhook advertised|ENETUNREACH|ETIMEDOUT|fetch failed' \
  /tmp/openclaw/openclaw-2026-04-27.log | tail -200

Also: separate but important — your gateway logs show non-loopback bind + insecure Control UI flags. Don’t expose that publicly while debugging.

Docs: https://docs.openclaw.ai/channels/telegram

#

Nice — this is the success signal:

[telegram] webhook local listener on http://127.0.0.1:8787/telegram-webhook
[telegram] webhook advertised to telegram on https://...ngrok-free.dev/telegram-webhook

OpenClaw only logs “advertised” after setWebhook succeeds, so the original registration failure is past that point now.

The remaining error:

deleteMyCommands failed

is Telegram command-menu sync noise, not webhook delivery. You can ignore it or keep:

#
channels: {
  telegram: {
    commands: { native: false }
  }
}

Now verify with the same bot token:

curl "https://api.telegram.org/bot<TOKEN>/getWebhookInfo"

If messages still don’t arrive:

  • ngrok logs should show POST /telegram-webhook
#
  • expected response should be 200
  • 401 means secret mismatch / wrong process behind tunnel
  • no POST means Telegram webhook is not actually pointed at this tunnel, likely wrong bot token/account

Docs: https://docs.openclaw.ai/channels/telegram

#

Those new lines are not Telegram webhook problems. The webhook already succeeded in the previous log.

These are separate config/tool warnings:

tools.allow allowlist contains unknown entries (...)

Means your tools.allow lists tools that are not currently registered. Either:

  • the mempalace MCP/plugin is not actually enabled/connected
  • those tool names changed
  • or ollama_web_search / ollama_web_fetch aren’t real OpenClaw tool IDs in this runtime

That can affect agent tool access, but not Telegram webhook delivery.

This one is also expected/safety-related:

#
bundle-mcp: server "mempalace": env "PYTHONPATH" is blocked for stdio startup safety and was ignored.

OpenClaw intentionally blocks interpreter-startup env vars like PYTHONPATH for stdio MCP servers. Use a venv/absolute Python executable or a small wrapper script that sets up the Python environment before launching the MCP server, instead of putting PYTHONPATH in the MCP env.

For Telegram now, focus on:

curl "https://api.telegram.org/bot<TOKEN>/getWebhookInfo"

and ngrok should show POST /telegram-webhook returning 200.

Docs:
https://docs.openclaw.ai/channels/telegram
https://docs.openclaw.ai/cli/mcp

lime silo
#

OpenClaw: 2026.4.25 (aa36ee6)
Issue: Webhook registration succeeds but immediately clears

Symptoms:

  1. setWebhook returns: {"ok":true,"result":true,"description":"Webhook was set"}
  2. getWebhookInfo immediately returns: {"url":null}

Tried:

  • With secret_token matching config
  • Without secret_token
  • Force delete + fresh register
  • drop_pending_updates=true

Result: Always "success" then immediately null

brave solarBOT
#

If setWebhook says success and getWebhookInfo immediately shows url: null, something is calling deleteWebhook right after registration.

In OpenClaw there are two likely paths:

  1. Another OpenClaw/poller using the same bot token
    Polling startup explicitly clears webhooks.

  2. The webhook gateway starts, then aborts/stops/restarts
    Webhook shutdown also calls deleteWebhook.

Check for both:

grep -Ei 'deleteWebhook|webhook advertised|webhook local|starting provider|polling|restart|stopping|abort|failed' \
  /tmp/openclaw/openclaw-2026-04-27.log | tail -250
#

Also find duplicate processes:

ps aux | grep -Ei 'openclaw|telegram|node' | grep -v grep

And make sure the bot token appears in only one enabled Telegram account/gateway. If you have accounts.default plus top-level token, or another VPS/local gateway still running polling, that would explain this perfectly.

The key signal is: successful webhook registration + immediate null is no longer an IPv4/ngrok issue — it’s webhook cleanup from another runtime/process.

lime silo
#

sysadmin@ollama1:~$ ps aux | grep -Ei 'openclaw|telegram|node' | grep -v grep
sysadmin 37800 48.1 2.7 20092844 1774248 ? Ssl 22:04 6:17 openclaw-gateway

brave solarBOT
#

That rules out a second local OpenClaw process, good. It does not rule out:

  • another host/VPS/laptop using the same bot token
  • the same gateway starting Telegram in polling mode for another account/config path
  • OpenClaw starting webhook, then stopping/restarting the channel and silently calling deleteWebhook

Best isolation test:

openclaw gateway stop

curl -s -X POST "https://api.telegram.org/bot<TOKEN>/setWebhook" \
  --data-urlencode "url=https://undecocted-kathleen-snowy.ngrok-free.dev/telegram-webhook"

curl -s "https://api.telegram.org/bot<TOKEN>/getWebhookInfo"
#

If it still immediately becomes empty/null while OpenClaw is stopped, something outside this gateway is clearing it or the token/url being checked isn’t the same one.

If it sticks while stopped, start OpenClaw and watch for channel restarts/config reloads:

openclaw gateway start

grep -Ei 'telegram|webhook|deleteWebhook|polling|health-monitor|restart|secrets.reload|starting provider' \
  /tmp/openclaw/openclaw-2026-04-27.log | tail -300

Also run:

openclaw channels status --probe --json
#

At this point, “set succeeds then clears” is definitely not ngrok/IPv4 anymore — it’s a deleteWebhook/polling/restart path somewhere.

lime silo
#

{"0":"{"subsystem":"model-fallback/decision"}","1":{"event":"model_fallback_decision","tags":["error_handling","model_fallback","candidate_failed"],"runId":"ac1e20c1-863d-42ae-be80-20819d78a84a","decision":"candidate_failed","requestedProvider":"lmstudio","requestedModel":"qwen/qwen3.5-35b-a3b","candidateProvider":"lmstudio","candidateModel":"qwen/qwen3.5-35b-a3b","attempt":1,"total":1,"reason":"timeout","status":408,"errorPreview":"LLM request timed out.","errorHash":"sha256:321034bb3121","isPrimary":true,"requestedModelMatched":true,"fallbackConfigured":false},"2":"model fallback decision","_meta":{"runtime":"node","runtimeVersion":"24.14.1","hostname":"unknown","name":"{"subsystem":"model-fallback/decision"}","parentNames":["openclaw"],"date":"2026-04-28T02:19:15.499Z","logLevelId":4,"logLevelName":"WARN","path":{"fullFilePath":"file:///home/sysadmin/.nvm/versions/node/v24.14.1/lib/node_modules/openclaw/dist/subsystem-BI-xRI3F.js:327:51","fileName":"subsystem-BI-xRI3F.js","fileNameWithLine":"subsystem-BI-xRI3F.js:327","fileColumn":"51","fileLine":"327","filePath":".nvm/versions/node/v24.14.1/lib/node_modules/openclaw/dist/subsystem-BI-xRI3F.js","filePathWithLine":".nvm/versions/node/v24.14.1/lib/node_modules/openclaw/dist/subsystem-BI-xRI3F.js:327","method":"logToFile"}},"time":"2026-04-27T22:19:15.499-04:00"}

brave solarBOT
#

That log is not Telegram-related.

It means the agent tried to call:

lmstudio / qwen/qwen3.5-35b-a3b

and the model request timed out:

reason: timeout
status: 408
fallbackConfigured: false

So: this can make replies fail or hang after a Telegram message reaches OpenClaw, but it does not explain getWebhookInfo.url = null or webhook clearing.

#

For the webhook issue, we still need the focused signal:

grep -Ei 'telegram|webhook|deleteWebhook|polling|health-monitor|restart|secrets.reload|starting provider' \
  /tmp/openclaw/openclaw-2026-04-27.log | tail -300

And the strongest isolation test is still:

openclaw gateway stop

curl -s -X POST "https://api.telegram.org/bot<TOKEN>/setWebhook" \
  --data-urlencode "url=https://undecocted-kathleen-snowy.ngrok-free.dev/telegram-webhook"

curl -s "https://api.telegram.org/bot<TOKEN>/getWebhookInfo"
#

If it clears while OpenClaw is stopped, something else has the bot token. If it only clears after OpenClaw starts, we look for deleteWebhook / polling / restart in logs.

For the model timeout separately: pick a model that responds reliably or configure fallback. Docs: https://docs.openclaw.ai/concepts/models

lime silo
#

OpenClaw: 2026.4.25 (aa36ee6)
Issue: Webhook registration appears successful but immediately clears

Symptoms:

  1. OpenClaw logs: "webhook advertised to telegram on https://...ngrok-free.dev/telegram-webhook"
  2. Manual curl setWebhook: {"ok":true,"result":true,"description":"Webhook was set"}
  3. Telegram API getWebhookInfo: {"url":null} (immediately after)

What works:

  • Webhook listener: Running on http://127.0.0.1:8787/telegram-webhook
  • Ngrok tunnel: Active and reachable
  • Manual test: POST returns 401 (expected, secret mismatch = working)
  • Messages: Arrive via polling (13s delay)

What doesn't:

  • Webhook registration sticks in Telegram API
  • Tried: ngrok, localtunnel, with/without secret, rate limit waits
  • Always: "success" response → url:null

Root cause: UNKNOWN

  • Not rate limiting (waited 30s, same result)
  • Not ngrok blocked (localtunnel same issue)
  • Not secret mismatch (tested without secret)
  • Not duplicate OpenClaw processes (only one PID 37800)
brave solarBOT
#

The key contradiction is this:

Messages arrive via polling

If polling is still receiving updates, some getUpdates/polling path is active, and Telegram webhooks + polling can’t coexist. Something is deleting/clearing the webhook.

One PID only rules out duplicate processes on that host. It does not rule out:

  • two Telegram accounts inside the same OpenClaw config using the same bot token
  • top-level channels.telegram.botToken plus channels.telegram.accounts.* duplication
  • another machine/service using the same bot token
  • checking getWebhookInfo with a different token than setWebhook

Do this exact same-token test:

#
TOKEN='<same bot token>'

curl -sS "https://api.telegram.org/bot$TOKEN/getMe"

curl -sS -X POST "https://api.telegram.org/bot$TOKEN/setWebhook" \
  --data-urlencode "url=https://undecocted-kathleen-snowy.ngrok-free.dev/telegram-webhook"

sleep 2

curl -sS "https://api.telegram.org/bot$TOKEN/getWebhookInfo"

Then hard-isolate OpenClaw:

#
openclaw gateway stop
pgrep -a -f 'openclaw|node.*openclaw'

Run the same set/get again while OpenClaw is stopped.

  • If it still clears: wrong token or another external poller/gateway has the token. Rotate the bot token in BotFather.
  • If it sticks while stopped but clears after OpenClaw starts: check duplicate Telegram account config / polling fallback inside OpenClaw.

Useful config check:

openclaw channels status --probe --json

And inspect whether the same Telegram token is configured in more than one place: top-level channels.telegram.* and channels.telegram.accounts.*.

lime silo
#

sysadmin@ollama1:~$ pgrep -a -f 'openclaw|node.*openclaw'
sysadmin@ollama1:~$ TOKEN='<Removed>'
sysadmin@ollama1:~$ curl -sS "https://api.telegram.org/bot$TOKEN/getMe"
{"ok":false,"error_code":401,"description":"Unauthorized"}sysadmin@ollama1:~$ curl -sS -X POST "https://api.telegram.org/bot$TOKEN/setWebhook" \ curl -sS -X POST "https://api.telegram.org/bot$TOKEN/setWebhook"
--data-urlencode "url=https://undecocted-kathleen-snowy.ngrok-free.dev/telegram-webhook"
{"ok":false,"error_code":401,"description":"Unauthorized"}sysadmin@ollama1:~$ curl -sS "https://api.telegram.org/bot$TOKEN/getWebhookInfo" curl -sS "https://api.telegram.org/bot$TOKEN/getWebhookInfo"
{"ok":false,"error_code":401,"description":"Unauthorized"}sysadmin@ollama1:~$

brave solarBOT
#

This test used an invalid token:

TOKEN='<Removed>'

So Telegram correctly returns:

{"ok":false,"error_code":401,"description":"Unauthorized"}

That means this isolation test didn’t actually test the bot. Run it locally with the real token, but don’t paste it here:

TOKEN='123456789:REAL_BOT_TOKEN_FROM_BOTFATHER'
#

curl -sS "https://api.telegram.org/bot$TOKEN/getMe"

curl -sS -X POST "https://api.telegram.org/bot$TOKEN/setWebhook" \
  --data-urlencode "url=https://undecocted-kathleen-snowy.ngrok-free.dev/telegram-webhook"

curl -sS "https://api.telegram.org/bot$TOKEN/getWebhookInfo"

Also make sure the command isn’t duplicated — your paste had curl ... \ curl ... on one line.

Expected first result should be {"ok":true,...}. If getMe is 401 with the real token, the token in shell/config is wrong or revoked.

lime silo
#

I did run it with the real token.. I removed it when I posted it here.. 8)

brave solarBOT
#

Ah, got it 😄 — but the important bit is the response, not the pasted token.

If you ran with the real token and got:

{"ok":false,"error_code":401,"description":"Unauthorized"}

then Telegram is saying that token is invalid/revoked/wrong. A valid bot token should make getMe return ok:true every time.

So before webhook debugging, confirm the exact token source:

TOKEN='real token, do not paste'

curl -sS "https://api.telegram.org/bot$TOKEN/getMe"
#

Expected:

{"ok":true,"result":{"id":...,"is_bot":true,"username":"..."}}

If getMe is 401, regenerate the token in BotFather and update OpenClaw config/env. If getMe is ok but getWebhookInfo is null, then we continue chasing the deleteWebhook/polling path.

lime silo
#

ok I mistyped the token during the first test..

#

sysadmin@ollama1:~$ curl -sS "https://api.telegram.org/bot$TOKEN/getMe" {"ok":true,"result":{"id":8658041202,"is_bot":true,"first_name":"askMaster Test","username":"Kloz_OpenClaw2_bot","can_join_groups":true,"can_read_all_group_messages":false,"supports_inline_queries":false,"can_connect_to_business":false,"has_main_web_app":false,"has_topics_enabled":false,"allows_users_to_create_topics":false,"can_manage_bots":false}}sysadmin@ollama1:~$

brave solarBOT
#

No worries — that happens. This is actually good because it removes the 401 confusion.

Run the clean test again with the corrected token, while OpenClaw is stopped:

openclaw gateway stop
pgrep -a -f 'openclaw|node.*openclaw'

TOKEN='real token, do not paste'

curl -sS "https://api.telegram.org/bot$TOKEN/getMe"

curl -sS -X POST "https://api.telegram.org/bot$TOKEN/setWebhook" \
  --data-urlencode "url=https://undecocted-kathleen-snowy.ngrok-free.dev/telegram-webhook"

sleep 2
#

curl -sS "https://api.telegram.org/bot$TOKEN/getWebhookInfo"

Interpretation:

  • getMe ok:true, getWebhookInfo.url sticks → OpenClaw is clearing it after startup.
  • getMe ok:true, getWebhookInfo.url still null while OpenClaw is stopped → another machine/app has the token, or Telegram rejected/cleared that exact URL.
  • getMe 401 → still wrong/revoked token.
#

Great — token is valid and we have the bot identity now:

@Kloz_OpenClaw2_bot

Now do the two webhook calls in the same shell with that same $TOKEN, while OpenClaw is still stopped:

curl -sS -X POST "https://api.telegram.org/bot$TOKEN/setWebhook" \
  --data-urlencode "url=https://undecocted-kathleen-snowy.ngrok-free.dev/telegram-webhook"

sleep 2

curl -sS "https://api.telegram.org/bot$TOKEN/getWebhookInfo"
#

What matters is the second response:

  • If url contains the ngrok URL while OpenClaw is stopped → Telegram is fine; OpenClaw is clearing it after startup.
  • If url is empty/null even while OpenClaw is stopped → something else is clearing it, or Telegram is rejecting that URL after accepting the call.
brave solarBOT
#

Perfect — that proves Telegram + ngrok + token are fine. The webhook sticks while OpenClaw is stopped.

So the remaining issue is inside OpenClaw startup/runtime: it’s either clearing the webhook or starting a polling path after startup.

Start OpenClaw, then immediately check webhook info and logs:

openclaw gateway start
sleep 15

curl -sS "https://api.telegram.org/bot$TOKEN/getWebhookInfo"

grep -Ei 'telegram|webhook|deleteWebhook|polling|health-monitor|restart|starting provider|failed' \
  /tmp/openclaw/openclaw-2026-04-27.log | tail -300

Also check the active Telegram account config shape. The common gotcha is webhookUrl at top level but the actual running account is accounts.default without inheriting what you expect, or duplicate token/config paths causing one account to poll:

#
openclaw channels status --probe --json

If webhook goes null only after openclaw gateway start, please paste the deleteWebhook/polling lines from that grep. That’s the smoking gun.

lime silo
#

{"0":"{"subsystem":"gateway/channels/telegram"}","1":"telegram deleteWebhook failed: Network request for 'deleteWebhook' failed!","_meta":{"runtime":"node","runtimeVersion":"24.14.1","hostname":"unknown","name":"{"subsystem":"gateway/channels/telegram"}","parentNames":["openclaw"],"date":"2026-04-28T00:29:24.947Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"file:///home/sysadmin/.nvm/versions/node/v24.14.1/lib/node_modules/openclaw/dist/subsystem-BI-xRI3F.js:328:14","fileName":"subsystem-BI-xRI3F.js","fileNameWithLine":"subsystem-BI-xRI3F.js:328","fileColumn":"14","fileLine":"328","filePath":".nvm/versions/node/v24.14.1/lib/node_modules/openclaw/dist/subsystem-BI-xRI3F.js","filePathWithLine":".nvm/versions/node/v24.14.1/lib/node_modules/openclaw/dist/subsystem-BI-xRI3F.js:328","method":"logToFile"}},"time":"2026-04-27T20:29:24.948-04:00"}

brave solarBOT
#

That deleteWebhook line is the smoking gun only if it’s from the latest startup — but note its timestamp is 20:29, while your successful webhook log was 21:44. So this may be an older polling attempt.

What it means: OpenClaw entered a path that calls deleteWebhook — usually polling startup or webhook shutdown.

Please run this after a fresh start, so we only inspect current logs:

openclaw gateway restart
sleep 20

curl -sS "https://api.telegram.org/bot$TOKEN/getWebhookInfo"

grep -Ei 'telegram|webhook|deleteWebhook|polling|starting provider|health-monitor|restart|failed' \
  /tmp/openclaw/openclaw-2026-04-27.log | tail -120

If you see deleteWebhook after webhook advertised, OpenClaw is shutting/restarting the webhook channel.

#

If you see deleteWebhook without webhook advertised, that account is starting in polling mode — likely webhookUrl isn’t on the active default account config.

For accounts.default, config should look like:

channels: {
  telegram: {
    accounts: {
      default: {
        botToken: "...",
        webhookUrl: "https://.../telegram-webhook",
        webhookSecret: "...",
      }
    }
  }
}
lime silo
#

{"0":"{"subsystem":"exec"}","1":"elevated command tail -100 /tmp/openclaw/openclaw-2026-04-27.log | grep -E ....*webhook|setWebhook|deleteWebhook|fail|error)" | tail -20","_meta":{"runtime":"node","runtimeVersion":"24.14.1","hostname":"unknown","name":"{"subsystem":"exec"}","parentNames":["openclaw"],"date":"2026-04-28T02:10:29.779Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"file:///home/sysadmin/.nvm/versions/node/v24.14.1/lib/node_modules/openclaw/dist/subsystem-BI-xRI3F.js:328:14","fileName":"subsystem-BI-xRI3F.js","fileNameWithLine":"subsystem-BI-xRI3F.js:328","fileColumn":"14","fileLine":"328","filePath":".nvm/versions/node/v24.14.1/lib/node_modules/openclaw/dist/subsystem-BI-xRI3F.js","filePathWithLine":".nvm/versions/node/v24.14.1/lib/node_modules/openclaw/dist/subsystem-BI-xRI3F.js:328","method":"logToFile"}},"time":"2026-04-27T22:10:29.779-04:00"}

brave solarBOT
#

That line is just OpenClaw logging that an exec command was run — not the output from the grep. Also the grep pattern looks malformed:

grep -E ....*webhook|setWebhook|deleteWebhook|fail|error)"

Use this exact safer command instead:

grep -Ei 'telegram|webhook|setWebhook|deleteWebhook|polling|health-monitor|restart|failed|error' \
  /tmp/openclaw/openclaw-2026-04-27.log | tail -160

If the log is JSON-ish and noisy, this is even narrower:

#
grep -Ei 'telegram.*(webhook|deleteWebhook|setWebhook|polling|failed)|webhook advertised|webhook local' \
  /tmp/openclaw/openclaw-2026-04-27.log | tail -120

Please paste the actual output lines from that, especially anything after the latest openclaw gateway restart.

lime silo
#

deleteWebhook is only in the exec of the command in the log

brave solarBOT
#

Gotcha — then no smoking-gun deleteWebhook from OpenClaw. Good catch.

At this point the clean facts are:

  • Manual setWebhook sticks while OpenClaw is stopped ✅
  • OpenClaw can log webhook advertised...
  • No real deleteWebhook in logs ✅
  • If messages still arrive via polling after webhook is set, that means either:
    • you’re observing old/delayed polling behavior from a previous run, or
    • OpenClaw is not actually running when webhook should receive, or
    • Telegram is posting but OpenClaw rejects/doesn’t process it

Next test: send a Telegram DM to the bot and watch ngrok.

Expected webhook path:

#
POST /telegram-webhook 200

Interpretation:

  • No POST in ngrok → Telegram isn’t using webhook / wrong bot token/account.
  • POST 401 → secret mismatch between Telegram webhook registration and OpenClaw config.
  • POST 200 but no OpenClaw response → webhook delivery is working; then it’s agent/model/routing/pairing.
  • POST 404/502/etc → tunnel/path/port issue.

Also verify webhook info now while OpenClaw is running:

curl -sS "https://api.telegram.org/bot$TOKEN/getWebhookInfo"