HKUDS/nanobot · error · RuntimeError

Telegram bot token was rejected by the server

Error message

Telegram bot token was rejected by the server

What it means

In start(), a persistent Telegram Application rejected the configured bot token (PTB raised InvalidToken on startup). This is a config error, not a transient network blip, so the loop tears down the app, stops retrying, and re-raises a scrubbed RuntimeError (via `from None`) so PTB's token-bearing message never reaches the log. Fires when the token is wrong, revoked, or malformed.

Solutions

  1. Fix the bot token in the Telegram channel config (get a valid one from @BotFather)
  2. Restart the channel/gateway after correcting the token
  3. Do not add automatic retries here; a rejected token never heals on its own
Defensive patterns

Strategy: fallback

When it happens

Trigger: Thrown at nanobot/channels/telegram/runtime.py:578 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of HKUDS/nanobot@42f37dc4c0 (2026-08-26). Data as JSON: /api/errors/7517db43d679b7e1. Report an issue: GitHub.

Appendix: source

Thrown at nanobot/channels/telegram/runtime.py:578

        if not self.config.token:
            self.logger.error("bot token not configured")
            return

        redirect_lib_logging("telegram")
        redirect_lib_logging("httpx", level="WARNING")

        self._running = True
        backoff = RESTART_BACKOFF_INITIAL_SECONDS
        while self._running:
            try:
                await self._start_app()
            except InvalidToken:
                # A config error, not a blip: fail the channel. The scrubbed
                # re-raise keeps PTB's token-bearing message out of the log.
                await self._teardown_app()
                self._running = False
                self.logger.error("bot token rejected by Telegram")
                raise RuntimeError("Telegram bot token was rejected by the server") from None
            except Exception as e:
                await self._teardown_app()
                if not self._running:
                    break
                if not self._is_transient_startup_error(e):
                    # Never heals on its own: fail instead of retrying forever
                    # while ChannelManager keeps reporting the channel running.
                    self._running = False
                    self.logger.error("startup failed: {}", self._format_telegram_error(e))
                    raise
                self.logger.error(
                    "startup failed: {}; retrying in {:.0f}s",
                    self._format_telegram_error(e),
                    backoff,
                )
                await self._idle(backoff)
                backoff = min(backoff * 2, RESTART_BACKOFF_MAX_SECONDS)
                continue

View on GitHub (pinned to 42f37dc4c0)