xtekky/gpt4free · error · RuntimeError

Response: {resp_json}

Error message

Response: {resp_json}

What it means

Raised when Qwen's completion endpoint (POST /api/v2/chat/completions) answers with content-type application/json instead of an SSE stream AND the JSON indicates failure (success=false or a data.code error). Qwen returns JSON only for refusals (rate limits, model restrictions, moderation), so any JSON response is treated as an error; this branch is the explicit failure case.

Source

Thrown at g4f/Provider/Qwen.py:665

                        msg_payload["size"] = aspect_ratio

                    async with session.post(
                        f"{cls.url}/api/v2/chat/completions?chat_id={conversation.chat_id}",
                        json=msg_payload,
                        headers=req_headers,
                        proxy=proxy,
                        timeout=timeout,
                        cookies=conversation.cookies,
                    ) as resp:
                        await cls.raise_for_status(resp)
                        if resp.headers.get("content-type", "").startswith(
                            "application/json"
                        ):
                            resp_json = await resp.json()
                            if resp_json.get("success") is False or resp_json.get(
                                "data", {}
                            ).get("code"):
                                raise RuntimeError(f"Response: {resp_json}")
                            else:
                                # cant stream resp after `resp_json = await resp.json()`, so it stick
                                raise RuntimeError(f"Response: {resp_json}")
                        # args["cookies"] = merge_cookies(args.get("cookies"), resp)
                        thinking_started = False
                        usage = None
                        async for chunk in sse_stream(resp):
                            try:
                                if "response.created" in chunk:
                                    conversation.parent_id = chunk.get(
                                        "response.created", {}
                                    ).get("response_id")
                                    yield conversation
                                error = chunk.get("error", {})
                                if error:
                                    raise ResponseError(
                                        f'{error["code"]}: {error["details"]}'
                                    )

View on GitHub (pinned to 973504e177)

Solutions

  1. Read the embedded resp_json — data.code names the refusal (rate limit vs model restriction).
  2. For rate limits: wait and retry later; the inner loop already retries 5 times with 2s sleeps, longer waits are needed for hard limits.
  3. Switch to an allowed default model.
  4. Update g4f for current model gating.

Example fix

# before
r = await Qwen.create_async_generator(model='qwen3-image-preview', msgs)

# after - fall back to default text model on refusal
try:
    r = await Qwen.create_async_generator(model='qwen3-image-preview', msgs)
except RuntimeError as e:
    r = await Qwen.create_async_generator(model=Qwen.default_model, msgs)
Defensive patterns

Strategy: try-catch

Type guard

def is_qwen_json_refusal(exc: Exception) -> bool:
    """True when Qwen answered JSON with an explicit failure code."""
    return isinstance(exc, RuntimeError) and str(exc).startswith('Response:') and 'success' in str(exc)

Try / catch

try:
    r = await Qwen.create_async_generator(model, msgs)
except RuntimeError as e:
    msg = str(e)
    if msg.startswith('Response:') and 'RateLimited' in msg:
        await asyncio.sleep(300)
        r = await Qwen.create_async_generator(model, msgs)
    elif msg.startswith('Response:'):
        r = await Qwen.create_async_generator(Qwen.default_model, msgs)  # model fallback
    else:
        raise

Prevention

When it happens

Trigger: Sending a completion when the API refuses before streaming: free-tier rate limit on the model (data.code like 'RateLimited'), model not allowed for anonymous users, or prompt flagged by moderation.

Common situations: Using restricted models (e.g. some image/thinking models) anonymously; bursts of completions after new-chat creation; retry loop already burned midtoken on prior 429s; g4f behind Qwen API changes.

Related errors


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