HKUDS/nanobot · error · RuntimeError

Mattermost client is not started

Error message

Mattermost client is not started

What it means

Raised by Mattermost _require_http_client (used by all _api_get/_api_post/_upload_file/_download_file helpers) when the channel runtime's httpx client is None — an API helper was invoked before start() completed or after stop() closed the client. All REST and file operations route through this lifecycle guard.

Solutions

  1. Ensure channel start() completed before sending or polling
  2. Restart the channel and requeue the failed operation
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at nanobot/channels/mattermost/runtime.py:649 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/c058f75fc4a5f17d. Report an issue: GitHub.

Appendix: source

Thrown at nanobot/channels/mattermost/runtime.py:649

            self._stream_root_ids[stream_id] = root_id
        committed = self._stream_committed.get(stream_id, "")
        buf = committed + delta
        self._stream_buffers[stream_id] = buf
        self._stream_committed[stream_id] = buf
        return

    def _clear_stream_state(self, stream_id: str) -> None:
        self._stream_root_ids.pop(stream_id, None)
        self._stream_posts.pop(stream_id, None)
        self._stream_buffers.pop(stream_id, None)
        self._stream_last_content.pop(stream_id, None)
        self._stream_committed.pop(stream_id, None)

    # API helpers ---------------------------------------------------------------

    def _require_http_client(self) -> httpx.AsyncClient:
        if self._http_client is None:
            raise RuntimeError("Mattermost client is not started")
        return self._http_client

    async def _api_get(self, path: str) -> dict[str, Any]:
        resp = await self._require_http_client().get(path)
        resp.raise_for_status()
        return cast(dict[str, Any], resp.json())

    async def _api_post(self, path: str, json_data: dict[str, Any]) -> dict[str, Any]:
        resp = await self._require_http_client().post(path, json=json_data)
        resp.raise_for_status()
        return cast(dict[str, Any], resp.json())

    async def _create_post(
        self,
        channel_id: str,
        message: str,
        *,
        root_id: str | None = None,

View on GitHub (pinned to 42f37dc4c0)