xtekky/gpt4free · error · ValueError
device_code is required for polling
Error message
device_code is required for polling
What it means
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.
Source
Thrown at g4f/Provider/github/GithubCopilot.py:267
"verification_uri", "https://github.com/login/device"
)
user_code = device_auth.get("user_code")
device_code = device_auth.get("device_code")
return {
"status": "pending",
"verification_uri": verification_uri,
"user_code": user_code,
"device_code": device_code,
"expires_in": device_auth.get("expires_in"),
"interval": device_auth.get("interval", 5),
}
@classmethod
async def oauth_poll(cls, device_code: str):
"""Poll GitHub token endpoint; save credentials once access_token is available."""
if not device_code:
raise ValueError("device_code is required for polling")
client = GithubOAuth2Client()
token_response = await client.pollDeviceToken({"device_code": device_code})
if token_response.get("status") == "pending":
return {"status": "pending", "message": "Authorization pending"}
if token_response.get("access_token"):
credentials = {
"access_token": token_response["access_token"],
"token_type": token_response.get("token_type", "bearer"),
"scope": token_response.get("scope", ""),
"expiry_date": int(time.time() * 1000) + (365 * 24 * 60 * 60 * 1000),
}
await client.sharedManager.saveCredentialsToFile(credentials)
return {"status": "success", "message": "GitHub Copilot OAuth successful"}
return {View on GitHub (pinned to 973504e177)
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
Example fix
# before result = await GithubCopilot.oauth_poll(auth_response) # after result = await GithubCopilot.oauth_poll(auth_response["device_code"])
Defensive patterns
Strategy: validation
Validate before calling
if not isinstance(device_code, str) or not device_code.strip():
raise ValueError("restart device flow: no device_code")
result = await GithubCopilot.oauth_poll(device_code.strip()) Type guard
def is_device_code(code: object) -> bool:
return isinstance(code, str) and len(code) > 20 and code.isalnum() Try / catch
try:
result = await GithubCopilot.oauth_poll(device_code)
except ValueError as e:
if 'device_code is required' in str(e):
auth = await GithubCopilot.oauth_begin() # restart flow
device_code = auth["device_code"] Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Device authorization error: {resp_json.get('error')} - {resp
- GitHub Copilot OAuth not configured. Please run 'g4f auth gi
- NO_TOKEN
- Device authorization failed {resp.status}: {resp_json}
- Device code expired. Please try again.
AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14).
Data as JSON: /api/errors/8e1ee102ab57c1a2.
Report an issue: GitHub.