xtekky/gpt4free · error · RuntimeError

Failed to decode JSON from PhindAi response: {text}

Error message

Failed to decode JSON from PhindAi response: {text}

What it means

Raised when the POST to PhindAi's admin-ajax.php returns a body that is not valid JSON (json.JSONDecodeError on response.json()). The raw text is embedded in the message, which usually exposes an HTML error/challenge page, a PHP fatal-error notice, or an empty body instead of the expected JSON envelope.

Source

Thrown at g4f/Provider/PhindAi.py:66

                match = re.search(r'"nonce":"([a-f0-9]+)"', html)
                if not match:
                    match = re.search(r"'nonce':'([a-f0-9]+)'", html)
                if not match:
                    raise RuntimeError("Failed to extract nonce from PhindAi response")
                nonce = match.group(1)

            # 2. Fetch the response
            ajax_url = f"{cls.url}/wp-admin/admin-ajax.php"
            payload = {"action": "phind_ai_send", "nonce": nonce, "message": prompt}

            async with session.post(ajax_url, data=payload) as response:
                await raise_for_status(response)
                try:
                    data = await response.json()
                except json.JSONDecodeError:
                    text = await response.text()
                    raise RuntimeError(
                        f"Failed to decode JSON from PhindAi response: {text}"
                    )

                if not data.get("success"):
                    raise RuntimeError(f"PhindAi API returned success=False: {data}")

                response_text = data.get("data", {}).get("response", "")
                return response_text

View on GitHub (pinned to 973504e177)

Solutions

  1. Inspect the embedded text — HTML title/Cloudflare markers tell you whether it is a block, an error page, or empty.
  2. Back off and retry to get a fresh nonce on a new session.
  3. Route through a different IP/proxy.
  4. Update g4f for endpoint/response changes.

Example fix

# before - hammering the endpoint in a tight loop
for msg in many_messages:
    r = await PhindAi.create_async_generator(model, [msg])

# after - fresh session + delay between calls
async with asyncio.Semaphore(1):
    for msg in many_messages:
        r = await PhindAi.create_async_generator(model, [msg])
        await asyncio.sleep(2)
Defensive patterns

Strategy: retry

Try / catch

try:
    result = await PhindAi.create_async_generator(model, messages)
except RuntimeError as e:
    if 'Failed to decode JSON' in str(e):
        if 'cloudflare' in str(e).lower():
            raise  # blocked: change IP
        await asyncio.sleep(5)
        result = await PhindAi.create_async_generator(model, messages)
    else:
        raise

Prevention

When it happens

Trigger: The ajax request returning HTML: invalid/expired nonce triggering a WP error page, rate-limit page, Cloudflare block, or server 500 with HTML body (raise_for_status already passed for 2xx only, so this is a 200-with-HTML or similar case the status check missed).

Common situations: Nonce expired between page fetch and ajax POST; aggressive request volume hitting WP rate limits; shared-hosting errors from phindafenough.fun; g4f out of sync with endpoint changes.

Understand the failure class

Related errors


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