xtekky/gpt4free · error · RuntimeError
Captcha solver returned an invalid token: {param!r}
Error message
Captcha solver returned an invalid token: {param!r} What it means
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.
Source
Thrown at g4f/Provider/glm/captcha_solver.py:281
element: '#captcha-element',
button: '#captcha-button',
captchaLogoImg: '',
showErrorTip: false,
success: (param) => { clearTimeout(timeout); resolve(param); },
fail: (err) => { clearTimeout(timeout); reject(new Error('SDK fail: ' + JSON.stringify(err))); },
getInstance: (inst) => { inst.startTracelessVerification(); }
});
});
})
"""
param = await tab.evaluate(
f"{solve_js}({{'region': {cfg['region']!r}, 'prefix': {cfg['prefix']!r}, "
f"'sceneId': {cfg['sceneId']!r}, 'timeout': {SOLVE_TIMEOUT_MS}}})",
await_promise=True,
)
if not isinstance(param, str) or not param:
raise RuntimeError(f"Captcha solver returned an invalid token: {param!r}")
debug.log("GLM captcha solved successfully")
return param
finally:
# Close the tab but keep the browser alive for reuse.
try:
await tab.close()
except Exception:
pass
async def _solve_with_retry() -> str:
"""Solve the captcha with retry, matching SOLVE_RETRIES attempts."""
last_err: Optional[Exception] = None
for attempt in range(1, SOLVE_RETRIES + 1):
try:
debug.log(f"GLM captcha: solve attempt {attempt}/{SOLVE_RETRIES}")
return await _solve_once()
except Exception as err:View on GitHub (pinned to 973504e177)
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.
Example fix
# before
CAPTCHA_CONFIG = {"region": "sgp", "prefix": "no8xfe", "sceneId": "didk33e0"}
# after (values re-read from window.AliyunCaptchaConfig on the live site)
CAPTCHA_CONFIG = {"region": "sgp", "prefix": "<new-prefix>", "sceneId": "<new-scene-id>"} Defensive patterns
Strategy: retry
Type guard
def is_valid_captcha_param(param) -> bool:
return isinstance(param, str) and len(param) > 0 Try / catch
try:
token = await get_captcha_verify_param()
except RuntimeError as e:
if 'invalid token' in str(e):
await asyncio.sleep(2) # risk-control cooldown, then retry once
token = await get_captcha_verify_param() Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- {captcha}
- Aliyun captcha SDK failed to load
- GLM captcha solving failed after {SOLVE_RETRIES} attempts: {
- Failed to obtain Turnstile token for DeepInfra request.
- {message or html}
AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14).
Data as JSON: /api/errors/854438e530b344f7.
Report an issue: GitHub.