{"record":{"id":"c7d463d2235e0b07","repo":"xtekky/gpt4free","slug":"no-refresh-token","errorCode":null,"errorMessage":"No refresh token","messagePattern":"No refresh token","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"g4f/Provider/qwen/qwenOAuth2.py","lineNumber":157,"sourceCode":"                    \"Accept\": \"application/json\",\n                },\n                data=object_to_urlencoded(body_data),\n            ) as resp:\n                resp_json = await resp.json()\n                if resp.status != 200:\n                    # Check for OAuth RFC 8628 responses\n                    if resp.status == 400:\n                        if \"error\" in resp_json:\n                            if resp_json[\"error\"] == \"authorization_pending\":\n                                return {\"status\": \"pending\"}\n                            if resp_json[\"error\"] == \"slow_down\":\n                                return {\"status\": \"pending\", \"slowDown\": True}\n                    raise Exception(f\"Token poll failed {resp.status}: {resp_json}\")\n                return resp_json\n\n    async def refreshAccessToken(self) -> Union[Dict, ErrorDataDict]:\n        if not self.credentials.get(\"refresh_token\"):\n            raise Exception(\"No refresh token\")\n        body_data = {\n            \"grant_type\": \"refresh_token\",\n            \"refresh_token\": self.credentials[\"refresh_token\"],\n            \"client_id\": QWEN_OAUTH_CLIENT_ID,\n        }\n        async with aiohttp.ClientSession(headers={\"user-agent\": \"\"}) as session:\n            async with session.post(\n                QWEN_OAUTH_TOKEN_ENDPOINT,\n                headers={\n                    \"Content-Type\": \"application/x-www-form-urlencoded\",\n                    \"Accept\": \"application/json\",\n                },\n                data=object_to_urlencoded(body_data),\n            ) as resp:\n                resp_json = await resp.json()\n                if resp.status != 200:\n                    if resp.status == 400:\n                        # Handle token expiration","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/Provider/qwen/qwenOAuth2.py#L139-L175","documentation":"Raised by QwenOAuth2.refreshAccessToken (qwenOAuth2.py:157) when refresh is attempted while the stored credentials contain no refresh_token. It is a pure precondition failure: the client was asked to refresh an authorization it never had (or no longer has).","triggerScenarios":"Calling refreshAccessToken() (directly or via the token manager) after setCredentials() with a dict lacking 'refresh_token' — e.g. after qwenOAuth2.py:177 reset credentials to empty QwenCredentials() on a prior 400.","commonSituations":"Refresh token previously expired and credentials were wiped, then another refresh is attempted; credentials file hand-created with only an access_token; race where two processes refresh concurrently and one clears state.","solutions":["Re-run the Qwen device authorization flow to obtain fresh tokens","Check credentials storage: ensure 'refresh_token' is present before enabling Qwen","Guard callers with an upfront check for refresh_token before requesting a refresh"],"exampleFix":"// before\nresp = await qwen_client.refreshAccessToken()  # may raise No refresh token\n\n// after\ncreds = qwen_client.getCredentials()\nif not creds.get(\"refresh_token\"):\n    raise RuntimeError(\"re-authentication required\")\nresp = await qwen_client.refreshAccessToken()","handlingStrategy":"validation","validationCode":"creds = qwen_client.getCredentials()\nassert creds.get(\"refresh_token\"), \"cannot refresh without a refresh token\"\nresp = await qwen_client.refreshAccessToken()","typeGuard":"def can_refresh(creds: dict) -> bool:\n    return isinstance(creds, dict) and isinstance(creds.get(\"refresh_token\"), str) and len(creds[\"refresh_token\"]) > 0","tryCatchPattern":"try:\n    resp = await qwen_client.refreshAccessToken()\nexcept Exception as exc:\n    if \"No refresh token\" in str(exc):\n        await start_qwen_device_login()\n    else:\n        raise","preventionTips":["Check for refresh_token before calling refresh — it is a precondition, not a runtime surprise","Persist complete credential sets (access, refresh, token_type, expiry)","Re-authenticate promptly after expiry wipes credentials"],"tags":["qwen","oauth","refresh-token","validation"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}