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

  1. 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.
  2. 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.
  3. Run from a residential/cleaner network environment — datacenter IPs are frequently flagged by Aliyun risk control.
  4. Update the bundled AliyunCaptcha.js.txt to the current SDK version deployed on z.ai.
  5. 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

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

Related errors


AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14). Data as JSON: /api/errors/854438e530b344f7. Report an issue: GitHub.