{"record":{"id":"d0238a51ccdc73ad","repo":"HKUDS/DeepTutor","slug":"github-copilot-auth-is-unavailable-validate-local","errorCode":null,"errorMessage":"GitHub Copilot auth is unavailable. Validate local Copilot auth or log in first.","messagePattern":"GitHub Copilot auth is unavailable\\. Validate local Copilot auth or log in first\\.","errorType":"error_code","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/llm/provider_core/github_copilot_provider.py","lineNumber":65,"sourceCode":"    async def _load_stored_github_token(self) -> str | None:\n        try:\n            from oauth_cli_kit.storage import FileTokenStorage\n        except ImportError:\n            return None\n        storage = FileTokenStorage(  # nosec B106 - token_filename is a file name, not a password.\n            token_filename=\"github-copilot.json\",\n            app_name=\"nanobot\",\n            import_codex_cli=False,\n        )\n        token = storage.load()\n        if not token or not getattr(token, \"access\", None):\n            return None\n        return str(token.access)\n\n    async def _exchange_token(self) -> str:\n        github_token = await self._load_stored_github_token()\n        if not github_token:\n            raise RuntimeError(\n                \"GitHub Copilot auth is unavailable. Validate local Copilot auth or log in first.\"\n            )\n\n        timeout = httpx.Timeout(20.0, connect=20.0)\n        async with httpx.AsyncClient(\n            timeout=timeout, follow_redirects=True, trust_env=True\n        ) as client:\n            response = await client.get(\n                DEFAULT_COPILOT_TOKEN_URL,\n                headers={\n                    \"Authorization\": f\"token {github_token}\",\n                    \"Accept\": \"application/json\",\n                    \"User-Agent\": USER_AGENT,\n                    \"Editor-Version\": EDITOR_VERSION,\n                    \"Editor-Plugin-Version\": EDITOR_PLUGIN_VERSION,\n                },\n            )\n            response.raise_for_status()","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/llm/provider_core/github_copilot_provider.py#L47-L83","documentation":"The GitHub Copilot provider exchanges a locally stored GitHub OAuth token for a short-lived Copilot token; if no stored GitHub token exists, _exchange_token raises RuntimeError telling the user to log in first.","triggerScenarios":"Calling chat via the Copilot provider with an empty/expired GitHub token store (e.g. ~/.config/github-copilot/ missing or devoid of hosts entries); _chat_impl → _exchange_token finds _load_stored_github_token() returning None.","commonSituations":"Never having run `deeptutor provider login github-copilot`; token store deleted; Copilot plugin auth files not present on a new machine/CI.","solutions":["Run `deeptutor provider login github-copilot` (or sign in via GitHub Copilot tooling) to populate the token store.","Verify the token store file exists and contains an oauth token for github.com.","Re-run after checking file permissions on the config directory."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef copilot_auth_present() -> bool:\n    # token store location used by the provider\n    return Path.home().joinpath('.config/github-copilot/hosts.json').exists()","typeGuard":null,"tryCatchPattern":"try:\n    resp = await provider.chat(messages)\nexcept RuntimeError as e:\n    if 'log in first' in str(e):\n        prompt_user_to_login('deeptutor provider login github-copilot')\n    else:\n        raise","preventionTips":["Run provider login during environment provisioning scripts","Check token store existence before enabling the Copilot provider","Re-login on a schedule or on auth failures"],"tags":["auth","github-copilot","login-required"],"backgroundTag":"oauth-token-missing","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}