xtekky/gpt4free · error · Exception

Failed to get upload URL

Error message

Failed to get upload URL

What it means

While uploading an image, LMArena POSTs a Next.js server action (next-action: generateUploadUrl) and parses the reply for a line starting with '1:'. This error means no such line existed: the response was not the expected server-action stream — usually an HTML Cloudflare or login page, because the action id in _next_actions is stale or the session lacks auth.

Source

Thrown at g4f/Provider/needs_auth/LMArena.py:483

                extension, file_type = detect_file_type(data_bytes)
                file_name = file_name or f"file-{len(data_bytes)}{extension}"
                async with session.post(
                    url=cls.url,
                    json=[file_name, file_type],
                    headers={
                        "accept": "text/x-component",
                        "content-type": "text/plain;charset=UTF-8",
                        "next-action": cls._next_actions["generateUploadUrl"],
                        "referer": cls.url,
                    },
                ) as response:
                    await raise_for_status(response)
                    text = await response.text()
                    line = next(
                        filter(lambda x: x.startswith("1:"), text.split("\n")), ""
                    )
                    if not line:
                        raise Exception("Failed to get upload URL")
                    chunk = json.loads(line[2:])
                    if not chunk.get("success"):
                        raise Exception("Failed to get upload URL")
                    uploadUrl = chunk.get("data", {}).get("uploadUrl")
                    key = chunk.get("data", {}).get("key")
                    if not uploadUrl:
                        raise Exception("Failed to get upload URL")

                async with session.put(
                    url=uploadUrl,
                    headers={
                        "content-type": file_type,
                    },
                    data=data_bytes,
                ) as response:
                    await raise_for_status(response)
                async with session.post(
                    url=cls.url,

View on GitHub (pinned to 973504e177)

Solutions

  1. Update g4f — the provider re-scrapes _next_action ids (LMArena.py:439) and newer releases track frontend builds
  2. Supply fresh lmarena.org cookies from a logged-in session so the server action is authorized
  3. Retry without the image to confirm text-only chat works, isolating the upload path
  4. Check egress IP reputation if the body looks like a Cloudflare challenge
Defensive patterns

Strategy: fallback

Validate before calling

def has_lmarena_auth(cookies: dict) -> bool:
    # anonymous sessions often cannot use server-action uploads
    return any(k in cookies for k in ("__Secure-next-auth.session-token",))

Try / catch

try:
    media = await upload_image(image)
except Exception as e:
    if "Failed to get upload URL" in str(e):
        media = None  # degrade gracefully: send text-only request

Prevention

When it happens

Trigger: Calling the LMArena provider with an image attachment when the generateUploadUrl action response contains no '1:'-prefixed line (raise at LMArena.py:483).

Common situations: LMArena deployed a new frontend build so the scraped action ids no longer resolve; cookies missing or expired so the action returns a login redirect; Cloudflare challenge page returned instead of the action stream.

Related errors


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