HKUDS/nanobot · error · RuntimeError

GitHub Copilot token exchange returned no token.

Error message

GitHub Copilot token exchange returned no token.

What it means

Raised in _get_copilot_access_token after the HTTP exchange with GitHub's Copilot token endpoint succeeded but the response body contained no token field. Indicates an unexpected/malformed response from the token endpoint (e.g. API change, error payload with 200 status, or proxy interference).

Solutions

  1. Retry the request; transient gateway issues can strip the payload
  2. Verify NANOBOT_COPILOT_TOKEN_URL override, if set, points at the official endpoint
  3. Re-login to refresh the underlying GitHub token and try again
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at nanobot/providers/github_copilot_provider.py:230 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/63a67985c7c41dd7. Report an issue: GitHub.

Appendix: source

Thrown at nanobot/providers/github_copilot_provider.py:230

            github_token = _load_github_token()
            if not github_token or not github_token.access:
                raise RuntimeError(
                    "GitHub Copilot is not logged in. Run: nanobot provider login github-copilot"
                )

            timeout = httpx.Timeout(20.0, connect=20.0)
            async with httpx.AsyncClient(timeout=timeout, follow_redirects=True, trust_env=True) as client:
                response = await client.get(
                    _resolve("NANOBOT_COPILOT_TOKEN_URL", DEFAULT_COPILOT_TOKEN_URL),
                    headers=_copilot_headers(github_token.access),
                )
                response.raise_for_status()
                payload = response.json()

            token = payload.get("token")
            if not token:
                raise RuntimeError("GitHub Copilot token exchange returned no token.")

            expires_at = payload.get("expires_at")
            if isinstance(expires_at, (int, float)):
                self._copilot_expires_at = float(expires_at)
            else:
                refresh_in = payload.get("refresh_in") or 1500
                self._copilot_expires_at = time.time() + int(refresh_in)
            self._copilot_access_token = str(token)
            return self._copilot_access_token

    async def _refresh_client_api_key(self) -> str:
        token = await self._get_copilot_access_token()
        client = await self._ensure_client()
        self.api_key = token
        cast(Any, client).api_key = token
        return token

    async def chat(

View on GitHub (pinned to 42f37dc4c0)