xtekky/gpt4free · error · Exception
Device authorization error: {resp_json.get('error')} - {resp
Error message
Device authorization error: {resp_json.get('error')} - {resp_json.get('error_description')} What it means
Raised by QwenOAuth2.startDeviceAuthorization (qwenOAuth2.py:122) when the device-authorization endpoint answers HTTP 200 but the response fails isDeviceAuthorizationSuccess() — i.e. it carries an OAuth 'error'/'error_description' pair (such as invalid_client or access_denied) instead of a device_code. A 200-with-error body means the request reached the server but was semantically rejected.
Source
Thrown at g4f/Provider/qwen/qwenOAuth2.py:122
"code_challenge_method": options["code_challenge_method"],
}
async with aiohttp.ClientSession(headers={"user-agent": ""}) as session:
async with session.post(
QWEN_OAUTH_DEVICE_CODE_ENDPOINT,
headers={
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
"x-request-id": str(uuid.uuid4()),
},
data=object_to_urlencoded(body_data),
) as resp:
resp_json = await resp.json()
if resp.status != 200:
raise Exception(
f"Device authorization failed {resp.status}: {resp_json}"
)
if not isDeviceAuthorizationSuccess(resp_json):
raise Exception(
f"Device authorization error: {resp_json.get('error')} - {resp_json.get('error_description')}"
)
return resp_json
async def pollDeviceToken(self, options: dict) -> Union[Dict, ErrorDataDict]:
body_data = {
"grant_type": QWEN_OAUTH_GRANT_TYPE,
"client_id": QWEN_OAUTH_CLIENT_ID,
"device_code": options["device_code"],
"code_verifier": options["code_verifier"],
}
async with aiohttp.ClientSession(headers={"user-agent": ""}) as session:
async with session.post(
QWEN_OAUTH_TOKEN_ENDPOINT,
headers={
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
},View on GitHub (pinned to 973504e177)
Solutions
- Upgrade g4f to pick up the current Qwen OAuth client constants
- Log resp_json.get('error') — invalid_client points at client_id skew, access_denied at policy blocks
- Retry once to rule out a transient gateway hiccup, then fall back to another provider
Defensive patterns
Strategy: try-catch
Try / catch
try:
resp = await oauth.startDeviceAuthorization(options)
except Exception as exc:
# message embeds error/error_description from a 200 body
if "invalid_client" in str(exc):
raise RuntimeError("g4f too old for Qwen OAuth; upgrade") from exc
raise Prevention
- Upgrade g4f when Qwen rotates OAuth constants
- Never assume status 200 means success in OAuth flows — check error fields
- Log the error_description verbatim for diagnosis
When it happens
Trigger: The endpoint returns JSON like {'error': 'invalid_client', 'error_description': ...} with status 200; triggered by a wrong/revoked QWEN_OAUTH_CLIENT_ID, disallowed grant_type, or API-gateway wrappers that always return 200.
Common situations: Qwen rotates the public client_id embedded in g4f and old versions fail; region-specific auth endpoints rejecting the flow; responses routed through gateways that normalize status codes to 200.
Related errors
- Device authorization failed {resp.status}: {resp_json}
- Token poll failed {resp.status}: {resp_json}
- device_code is required for polling
- Device authorization failed {resp.status}: {resp_json}
- Device authorization error: {resp_json.get('error')} - {resp
AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14).
Data as JSON: /api/errors/e16c27bd0fafe789.
Report an issue: GitHub.