{"record":{"id":"8e1ee102ab57c1a2","repo":"xtekky/gpt4free","slug":"device-code-is-required-for-polling","errorCode":null,"errorMessage":"device_code is required for polling","messagePattern":"device_code is required for polling","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"g4f/Provider/github/GithubCopilot.py","lineNumber":267,"sourceCode":"            \"verification_uri\", \"https://github.com/login/device\"\n        )\n        user_code = device_auth.get(\"user_code\")\n        device_code = device_auth.get(\"device_code\")\n\n        return {\n            \"status\": \"pending\",\n            \"verification_uri\": verification_uri,\n            \"user_code\": user_code,\n            \"device_code\": device_code,\n            \"expires_in\": device_auth.get(\"expires_in\"),\n            \"interval\": device_auth.get(\"interval\", 5),\n        }\n\n    @classmethod\n    async def oauth_poll(cls, device_code: str):\n        \"\"\"Poll GitHub token endpoint; save credentials once access_token is available.\"\"\"\n        if not device_code:\n            raise ValueError(\"device_code is required for polling\")\n\n        client = GithubOAuth2Client()\n        token_response = await client.pollDeviceToken({\"device_code\": device_code})\n\n        if token_response.get(\"status\") == \"pending\":\n            return {\"status\": \"pending\", \"message\": \"Authorization pending\"}\n\n        if token_response.get(\"access_token\"):\n            credentials = {\n                \"access_token\": token_response[\"access_token\"],\n                \"token_type\": token_response.get(\"token_type\", \"bearer\"),\n                \"scope\": token_response.get(\"scope\", \"\"),\n                \"expiry_date\": int(time.time() * 1000) + (365 * 24 * 60 * 60 * 1000),\n            }\n            await client.sharedManager.saveCredentialsToFile(credentials)\n            return {\"status\": \"success\", \"message\": \"GitHub Copilot OAuth successful\"}\n\n        return {","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/Provider/github/GithubCopilot.py#L249-L285","documentation":"A plain ValueError raised at the top of GithubCopilot.oauth_poll when the caller passes an empty/None device_code. The device-code polling endpoint (RFC 8628) requires the code returned by the initial device authorization response (oauth_begin), so an empty value is rejected immediately before any network call.","triggerScenarios":"Calling oauth_poll('') or oauth_poll(None); losing the device_code between the oauth_begin response and the poll step (e.g. CLI restart, serialization bug, passing the whole response dict instead of its 'device_code' field).","commonSituations":"Custom auth orchestration code that stores the wrong field from the device authorization response; retry logic that re-enters polling without persisting the device_code.","solutions":["Pass the 'device_code' string from the dict returned by oauth_begin(), not the whole dict or the user_code","Persist the device_code (with its expires_in) between the begin and poll steps if the flow spans processes","Guard with 'if not device_code: restart the flow' before calling oauth_poll"],"exampleFix":"# before\nresult = await GithubCopilot.oauth_poll(auth_response)\n# after\nresult = await GithubCopilot.oauth_poll(auth_response[\"device_code\"])","handlingStrategy":"validation","validationCode":"if not isinstance(device_code, str) or not device_code.strip():\n    raise ValueError(\"restart device flow: no device_code\")\nresult = await GithubCopilot.oauth_poll(device_code.strip())","typeGuard":"def is_device_code(code: object) -> bool:\n    return isinstance(code, str) and len(code) > 20 and code.isalnum()","tryCatchPattern":"try:\n    result = await GithubCopilot.oauth_poll(device_code)\nexcept ValueError as e:\n    if 'device_code is required' in str(e):\n        auth = await GithubCopilot.oauth_begin()  # restart flow\n        device_code = auth[\"device_code\"]","preventionTips":["Extract auth['device_code'] immediately after oauth_begin and store it in one variable","Persist device_code with a timestamp when the flow spans processes","Never pass the whole authorization response dict to oauth_poll"],"tags":["oauth","device-flow","validation","github-copilot"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}