When a NanoClaw Telegram bot stops responding, the first move is not a fix — it is deciding whether inbound messages are reaching the host at all, because two separately reported NanoClaw failures produce that complaint with opposite signatures. In one, inbound dies while outbound delivery and scheduled tasks keep working, so every surface an operator checks looks healthy. In the other, nothing sends either, and the log marks messages delivered that were never sent. Same complaint, different causes, and a remedy for one does nothing for the other.
One disambiguation before anything else, because search results for this phrase are mostly about a different product. OpenClaw is a separate and far larger project — 390,207 stars and a NOASSERTION license when its repository API record was read on September 21, 2026 — and NanoClaw's own homepage positions itself against it. NanoClaw is nanocoai/nanoclaw: MIT, not archived, not a fork, 30,818 stars, 1,068 open issues, last pushed September 19, 2026 (GitHub API, same date). The older qwibitai/nanoclaw address returns a 301 to it, so that is the same project renamed rather than a second one. The two projects share no Telegram code path — NanoClaw installs its own adapter by copying source from its channels branch (add-telegram skill) — so an OpenClaw remedy does not transfer. For the difference in full, see NanoClaw vs OpenClaw.
Read the signature before you touch anything
Each row below is a distinct, separately reported failure with its own confirming check. All eight were read on September 21, 2026 from NanoClaw's own issue tracker, shipped skills and channel documentation.
| What you observe | Most likely cause | The check that confirms it |
|---|---|---|
| Nothing you send is answered, but replies, scheduled messages and outbound delivery still work | The polling loop is failing and retrying forever — issue #3728, open | A Telegram polling request failed line carrying a large consecutiveFailures value; success logs nothing, so a quiet log is not proof of health |
Nothing sends either; the main log shows Message delivered with platformMsgId=undefined beside No adapter for channel type | Two host instances at once — the second poller gets a 409 from Telegram, which aborts setup before the adapter registers (/debug skill, PR #2225) | The absence of a Channel adapter started line for telegram, plus a second process in ps aux |
| Direct messages and groups work; channel posts never arrive at all | A stale server-side update filter on the bot token — issue #2989, open | Was this token previously polled by NanoClaw v1 or another bot library? Telegram's own Bot API says of allowed_updates: "If not specified, the previous setting will be used." |
| The bot answers direct messages but ignores ordinary group text | Group Privacy is on (add-telegram skill) | BotFather, /mybots, Bot Settings, Group Privacy — and re-add the bot to the group afterwards |
| Messaging works, but pairing never completes | The boot-time getMe failed once and a null bot username is cached for the process lifetime — issue #3162, open | One Telegram getMe failed warning at boot, minutes before you tried to pair; the issue reports a restart clears it |
| Setup aborts with "Couldn't reach Telegram", or startup stalls for around a minute and a half | IPv6 configured with no working route — issue #2377, open | curl -4 against the Bot API succeeds while curl -6 cannot connect |
| Most replies arrive, but ones containing certain URLs never do | Outbound formatting, not receipt: issue #3569 reports the pinned adapter truncating messages with an odd count of unescaped markers | Telegram rejects the send; two single-underscore URLs cancel out, which makes it look intermittent |
| A second bot you just added never comes online | Instance variables are read once at start, and a duplicate token is skipped (channel documentation) | A warning in logs/nanoclaw.error.log (add-telegram skill); Telegram allows one poller per token, so each bot needs its own BotFather token |
NanoClaw's official first-line diagnostics are two log files plus ncl sessions list, ncl dropped-messages list and ncl wirings list. No released version ships a channel-liveness command, so the triage below leans on the log lines instead.
# 1. Is inbound polling failing, and for how long?
# A rising consecutiveFailures count is the #3728 signature.
grep "Telegram polling request failed" logs/nanoclaw.error.log | tail -5
# 2. Did the Telegram adapter ever register this boot?
# Its ABSENCE is the duplicate-host signature, not an error line.
grep "Channel adapter started" logs/nanoclaw.log | tail -10
# 3. Is a second host holding the polling session?
ps aux | grep 'nanoclaw/dist/index.js' | grep -v grep
systemctl --user list-units 'nanoclaw*' --all # Linux systemd installsWhy everything looks healthy while inbound is dead
This is structural, and it is the part that wastes the most time. NanoClaw's README describes the path as messaging app to host router to an inbound database, into the container, out to an outbound database, and back through delivery. Delivery polls the outbound database on its own, and a 60-second host sweep independently wakes due and recurring messages. Inbound is the only stage that depends on the Telegram poller — which is exactly why the reporter of issue #3728 saw the host stay active, outbound delivery keep working and scheduled tasks keep firing through roughly four days of total inbound silence, with 11,178 consecutive failures recorded.
The health hook that should have caught it does not. NanoClaw's published adapter interface reference says of isConnected() that it is "not currently called by the host outside tests" and that "the bridge always returns true". Trunk has since moved: an ncl status command that reports a per-adapter connected flag landed on main on September 15, 2026, after the v2.3.0 release, which makes the documentation accurate for every released version and stale for trunk. Treat that command as unreleased internals rather than advice — it is registered hidden and host-only and appears in no documentation. For Telegram the two roads meet anyway: neither 4.29.0 nor 4.41.0 of the adapter implements isConnected at all (both dist builds were grepped for this page), so the probe falls back to true either way.
The documentation has a matching hole. The troubleshooting page carries a section headed "Webhook channel is silent" and no polling equivalent, and its "Agent never replies" walkthrough opens at "Did the router accept it?" with ncl dropped-messages list — a step that already assumes the message reached the host. When the poller is dead there are no dropped-message rows to find, because the router never saw the message. Issue #2989 records the same dead end for its own cause: no log lines, no dropped-message rows, nothing to debug from.
There is no fix version, so plan around that
Issue #3728 is open with zero comments, zero labels and no milestone, and its updated timestamp still equals its creation timestamp of September 6, 2026. The newest release is v2.3.0 from August 24, 2026, and the only commit on the channels branch since September 1 is a Mattermost fix. The same is true of the stale-filter case: the pull request that would pin an explicit update list has been open against channels since August 22, 2026, and the current branch source contains no occurrence of allowedUpdates at all. The single-instance host lock that would have prevented the duplicate-host case was closed without merging. So the honest framing is mitigation, not a version number.
Three things are worth knowing before you write your own patch. First, a local edit to src/channels/telegram.ts does not survive: the add-telegram skill copies that file in from the channels branch with the instruction to overwrite because the branch is canonical, and the update skill refreshes every installed channel — which is precisely how the #3728 reporter lost that fix on each update. Second, the reporter's watchdog is a warning as much as a recipe: the counter-only first version caused a worse three-day outage, because the poller ended up stopped rather than failing, so no further failures were logged and the counter never reached its threshold. The second version used two independent signals and never left the poller stopped. None of that is shipped, endorsed or independently verified. Third, whatever you build, test recovery in both directions: outbound success proves nothing about inbound, so the check that matters is a fresh message sent from the paired chat that produces a new inbound row.
A Telegram channel failure is not a model or API problem
Worth stating plainly, because the obvious next search sends people the wrong way. NanoClaw's credentials documentation says channel tokens like TELEGRAM_BOT_TOKEN stay in .env and are used by the host process, not the containers, while model credentials live in the vault and are injected into outbound requests in flight. Inbound messages reach the router and the session's inbound database before any provider is chosen, since the provider resolves when the container spawns (agent providers documentation). No base URL, key, gateway or provider swap repairs a dead polling loop, a stale update filter, a poller collision, Group Privacy or a broken IPv6 route.
The genuine crossover runs the other way. NanoClaw's README lists Claude Code among its requirements specifically for /customize, /debug and every /add-channel skill, so repairing a channel needs it on the host even if your agent groups run on something else. The host requirements are macOS or Linux, Windows through WSL2, Node.js 22 or newer, pnpm 10 or newer, and Docker — and note that nanoclaw.dev still advertises Node.js 20 or newer while the README and the v2.3.0 changelog make 22 a hard floor. Go by the changelog, which calls the bump breaking.
What NanoClaw and its Telegram channel actually cost
| Line item | What it costs | Where that comes from |
|---|---|---|
| NanoClaw itself | $0, MIT licensed, no paid tier and no user accounts | nanoclaw.dev: "NanoClaw is free and open source under the MIT license." |
| The community portal account | Free and opt-in; everything else works without it | The project README |
| The Telegram bot token | $0 to create in BotFather, and nothing to buy for one paired chat — Telegram's optional Paid Broadcasts tier only applies above 30 messages a second | Telegram Bot API; polling mode also means no public URL, webhook or open port, per the channel documentation |
| Model usage | Whatever the attached provider charges; NanoClaw itself charges nothing for it | nanoclaw.dev FAQ: "Your agent provider may charge for model usage." |
| Docker | Required on the host; Docker's own subscription terms apply above its free-use thresholds | Not checked for this page — read Docker's pricing page before budgeting it |
There is no paid tier to buy your way out of an unresponsive bot, which is the useful thing that table tells you. The money only starts once the channel works again and the agent is answering. The figures below are illustrative token arithmetic, not measured task costs and not a bill ceiling: assume one paired chat at 25 turns a day, 20,000 uncached input and 900 output tokens per turn, over 30 days. Rates are live Kunavo catalog prices per million tokens.
| Model | Input / output per 1M | Estimated month |
|---|---|---|
| Claude Haiku 4.5 | $0.40 / $2.00 | $7.35 |
| Gemini 3.8 Flash | $0.525 / $2.625 | $9.65 |
| GPT-5.6 Terra | $0.70 / $4.20 | $13.34 |
| Claude Sonnet 4.6 | $1.20 / $6.00 | $22.05 |
| Claude Opus 5 | $2.00 / $10.00 | $36.75 |
Scale that by your own traffic before treating it as a budget, and note the assumption doing the most work: nothing is served from cache. A long-lived agent session resends context, so cache behavior moves this number more than the per-token gap between two neighbouring models does. Kunavo's catalog amount is a billing floor rather than a cap — when the upstream reports its charge, the bill is the greater of catalog cost and upstream cost times the applicable markup. The minimum top-up is $10 in prepaid credit, a funding minimum rather than a task fee or a subscription; see billing details.
| Route for the agent's model | Wins when | What it does not do |
|---|---|---|
| Direct vendor API | You stay on one vendor's flagship and want that vendor's own caching and batch terms | A second vendor means a second account and a second balance |
| An OpenAI-compatible or Anthropic-compatible gateway | You switch models per agent group and want one key and one balance | NanoClaw's native provider is the Claude Agent SDK, so a custom base URL must speak that wire format; an OpenAI-format endpoint is reached through the OpenCode provider skill, which routes models through OpenCode's own config |
| A subscription | Flat-rate heavy daily use suits you better than metered tokens | NanoClaw sells no subscription of its own; the flat rate belongs to the provider |
| A local model | Small or private work with no hosted-model bill | NanoClaw's own Ollama skill is described as targeting an older configuration path and not a supported drop-in switch on current main |
None of those four choices touches the Telegram path. For the provider side in full — the two environment variables setup reads, what the container actually sees, and where OpenCode and Codex fit — see NanoClaw API costs and providers. If you are wiring the default Claude runtime to a custom endpoint, the Claude Code integration guide and base URL reference cover the configuration, and you can create a Kunavo account when you are ready to fund a key. Kunavo has not runtime-tested NanoClaw, and a published setup guide is a configuration reference rather than a compatibility test.
FAQ
Why did my NanoClaw Telegram bot stop responding?
Start by asking whether messages are still leaving the host. If replies and scheduled messages still arrive but nothing you send is answered, inbound polling is the suspect: NanoClaw issue #3728 reports that the adapter's polling loop retries getUpdates forever with a 30-second backoff ceiling, never gives up and logs nothing on a successful poll, so the failure is invisible. If nothing sends either, and the log shows "Message delivered" entries with platformMsgId=undefined next to "No adapter for channel type" warnings, NanoClaw's own /debug skill names two service instances running at once as the cause. Those two have opposite remedies, so identify the signature before changing anything.
Is there a fixed version of the NanoClaw Telegram polling bug?
No, not as of September 21, 2026. Issue #3728 is open with zero comments, zero labels and no milestone, and its updated timestamp still equals the date it was filed, September 6, 2026. The newest NanoClaw release is v2.3.0 from August 24, 2026, so nothing has shipped since the report, and the only commit on the channels branch since September 1 is a Mattermost fix. Anyone telling you to upgrade to a specific NanoClaw version for this is naming a version that does not exist.
Does upgrading @chat-adapter/telegram fix it?
Not the silent-death path. NanoClaw pins @chat-adapter/telegram at exactly 4.29.0, published May 18, 2026, while npm's latest dist-tag is 4.41.0 from September 18, 2026. Both tarballs were downloaded and compared for this page: the getUpdates transport-failure branch is materially identical in the two builds — the same consecutiveFailures counter, the same 30-second backoff ceiling, the same warning line, no give-up and no escalation, and a successful poll still logs nothing. 4.41.0 did rewrite other parts of the loop. This page states that as a fact about the code and does not recommend bumping the pin: NanoClaw's add-telegram skill says the supply-chain policy rejects ranges, the two bump pull requests read for this page (#3460 and #3570) are open and unmerged, and nobody here tested what else a bump changes.
Will changing my API provider or base URL fix a Telegram problem?
No. NanoClaw's credentials documentation states that channel tokens like TELEGRAM_BOT_TOKEN stay in .env and are used by the host process, not the containers, while model credentials go into the vault and are injected into container traffic. An inbound Telegram message reaches the router and the session's inbound database before a provider is ever resolved, which happens when the container spawns. So a different endpoint, key or gateway cannot repair a dead polling loop, a stale server-side update filter, a poller collision, Group Privacy or a broken IPv6 route. The one real crossover runs the other way: NanoClaw's README lists Claude Code as a requirement for /debug and every /add-channel skill, so channel repair needs it on the host even on an install whose agent runs somewhere else.
The bot answers direct messages but ignores the group. Why?
That is usually Telegram's Group Privacy setting rather than a NanoClaw defect. NanoClaw's add-telegram skill states that with Group Privacy on the bot only sees addressed commands and replies, not ordinary text, and that you turn it off in BotFather under /mybots, your bot, Bot Settings, Group Privacy — then remove and re-add the bot to the group so the change takes effect. A separate case looks similar but is not: NanoClaw issue #2989 reports that a bot token previously polled with a narrower allowed_updates filter keeps that filter server-side forever, which silently drops channel posts while direct messages and groups keep working.
Pairing never completes, but the bot still works. What is wrong?
NanoClaw issue #3162 describes exactly that shape: if the getMe call at channel start fails once, the bot username is cached as null for the whole process lifetime and every pairing code you send is treated as an ordinary message, with no attempt recorded and the installer waiting forever. The only trace is a single warning line at boot, minutes before you try to pair, and the issue says a restart with no other change fixes it. The current channels-branch adapter still makes that lookup once, without a retry, and caches the result. Note also that NanoClaw's documentation describes a one-time 6-digit code with up to 5 regenerated codes per run, while issue #3162 calls it a 4-digit code; go by the documentation.
Checked September 21, 2026: the nanocoai/nanoclaw repository record and release list, the open/closed states of issues #2377, #2989, #3162, #3569 and #3728 and of pull requests #2225, #2697, #3449, #3460 and #3570, the channels-branch Telegram adapter source, both the pinned 4.29.0 and the current 4.41.0 adapter builds from npm, NanoClaw's channel, credentials, troubleshooting and adapter-interface documentation, its add-telegram and debug skills, and Telegram's Bot API page. Nothing on this page was executed against a running NanoClaw install. Kunavo token rates come from the live catalog, and the dollar figures are illustrative token arithmetic.