{"record":{"id":"854438e530b344f7","repo":"xtekky/gpt4free","slug":"captcha-solver-returned-an-invalid-token-param-r","errorCode":null,"errorMessage":"Captcha solver returned an invalid token: {param!r}","messagePattern":"Captcha solver returned an invalid token: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"g4f/Provider/glm/captcha_solver.py","lineNumber":281,"sourceCode":"                    element: '#captcha-element',\n                    button: '#captcha-button',\n                    captchaLogoImg: '',\n                    showErrorTip: false,\n                    success: (param) => { clearTimeout(timeout); resolve(param); },\n                    fail: (err) => { clearTimeout(timeout); reject(new Error('SDK fail: ' + JSON.stringify(err))); },\n                    getInstance: (inst) => { inst.startTracelessVerification(); }\n                });\n            });\n        })\n        \"\"\"\n\n        param = await tab.evaluate(\n            f\"{solve_js}({{'region': {cfg['region']!r}, 'prefix': {cfg['prefix']!r}, \"\n            f\"'sceneId': {cfg['sceneId']!r}, 'timeout': {SOLVE_TIMEOUT_MS}}})\",\n            await_promise=True,\n        )\n        if not isinstance(param, str) or not param:\n            raise RuntimeError(f\"Captcha solver returned an invalid token: {param!r}\")\n        debug.log(\"GLM captcha solved successfully\")\n        return param\n    finally:\n        # Close the tab but keep the browser alive for reuse.\n        try:\n            await tab.close()\n        except Exception:\n            pass\n\n\nasync def _solve_with_retry() -> str:\n    \"\"\"Solve the captcha with retry, matching SOLVE_RETRIES attempts.\"\"\"\n    last_err: Optional[Exception] = None\n    for attempt in range(1, SOLVE_RETRIES + 1):\n        try:\n            debug.log(f\"GLM captcha: solve attempt {attempt}/{SOLVE_RETRIES}\")\n            return await _solve_once()\n        except Exception as err:","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/Provider/glm/captcha_solver.py#L263-L299","documentation":"Raised after the in-page captcha solve JS runs: tab.evaluate awaited the solve promise and returned a value that is not a non-empty string. The promise resolves with the captcha_verify_param token; anything else (None, dict, empty string) means the SDK's startTracelessVerification() path failed without rejecting (e.g. captchaGetState callback returned failure) or the JS returned undefined. The f-string interpolates the actual value ({param!r}) so the returned payload is visible in the error.","triggerScenarios":"The solve JS promise resolves with undefined because the Aliyun SDK's captcha handler completed abnormally (risk control flagged the headless session); the SDK rejected internally but a callback swallowed the error and resolved with nothing; the tab was closed mid-solve so evaluate returned None; or the CAPTCHA_CONFIG (region/prefix/sceneId) no longer matches z.ai's window.AliyunCaptchaConfig, so the SDK never produces a token.","commonSituations":"Aliyun bot detection improving and rejecting traceless verification from datacenter IPs; z.ai rotating the captcha sceneId/prefix making the hardcoded CAPTCHA_CONFIG stale; anti-headless fingerprinting defeating the bundled stealth script (STEALTH_INIT_SCRIPT) on newer Chrome versions.","solutions":["Inspect the repr in the error message: None usually means the solve promise resolved without a token (SDK/config mismatch); a dict often means an error object was returned — act accordingly.","Re-check z.ai's live page config: open chat.z.ai, read window.AliyunCaptchaConfig, and update CAPTCHA_CONFIG in g4f/Provider/glm/captcha_solver.py if region/prefix/sceneId changed.","Run from a residential/cleaner network environment — datacenter IPs are frequently flagged by Aliyun risk control.","Update the bundled AliyunCaptcha.js.txt to the current SDK version deployed on z.ai.","Strengthen stealth mitigations (USER_AGENT, STEALTH_INIT_SCRIPT) to match a current Chrome build."],"exampleFix":"# before\nCAPTCHA_CONFIG = {\"region\": \"sgp\", \"prefix\": \"no8xfe\", \"sceneId\": \"didk33e0\"}\n\n# after (values re-read from window.AliyunCaptchaConfig on the live site)\nCAPTCHA_CONFIG = {\"region\": \"sgp\", \"prefix\": \"<new-prefix>\", \"sceneId\": \"<new-scene-id>\"}","handlingStrategy":"retry","validationCode":null,"typeGuard":"def is_valid_captcha_param(param) -> bool:\n    return isinstance(param, str) and len(param) > 0","tryCatchPattern":"try:\n    token = await get_captcha_verify_param()\nexcept RuntimeError as e:\n    if 'invalid token' in str(e):\n        await asyncio.sleep(2)  # risk-control cooldown, then retry once\n        token = await get_captcha_verify_param()","preventionTips":["Cache and reuse tokens for their full 45s TTL instead of solving per request (get_captcha_verify_param already does).","Avoid hammering z.ai from datacenter IPs — Aliyun risk control remembers.","Keep CAPTCHA_CONFIG synced with window.AliyunCaptchaConfig on the live site."],"tags":["captcha","glm","browser","anti-bot"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}