{"record":{"id":"e1c82485fca6d5e5","repo":"xtekky/gpt4free","slug":"failed-to-get-upload-url","errorCode":null,"errorMessage":"Failed to get upload URL","messagePattern":"Failed to get upload URL","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"g4f/Provider/needs_auth/LMArena.py","lineNumber":483,"sourceCode":"                extension, file_type = detect_file_type(data_bytes)\n                file_name = file_name or f\"file-{len(data_bytes)}{extension}\"\n                async with session.post(\n                    url=cls.url,\n                    json=[file_name, file_type],\n                    headers={\n                        \"accept\": \"text/x-component\",\n                        \"content-type\": \"text/plain;charset=UTF-8\",\n                        \"next-action\": cls._next_actions[\"generateUploadUrl\"],\n                        \"referer\": cls.url,\n                    },\n                ) as response:\n                    await raise_for_status(response)\n                    text = await response.text()\n                    line = next(\n                        filter(lambda x: x.startswith(\"1:\"), text.split(\"\\n\")), \"\"\n                    )\n                    if not line:\n                        raise Exception(\"Failed to get upload URL\")\n                    chunk = json.loads(line[2:])\n                    if not chunk.get(\"success\"):\n                        raise Exception(\"Failed to get upload URL\")\n                    uploadUrl = chunk.get(\"data\", {}).get(\"uploadUrl\")\n                    key = chunk.get(\"data\", {}).get(\"key\")\n                    if not uploadUrl:\n                        raise Exception(\"Failed to get upload URL\")\n\n                async with session.put(\n                    url=uploadUrl,\n                    headers={\n                        \"content-type\": file_type,\n                    },\n                    data=data_bytes,\n                ) as response:\n                    await raise_for_status(response)\n                async with session.post(\n                    url=cls.url,","sourceCodeStart":465,"sourceCodeEnd":501,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/Provider/needs_auth/LMArena.py#L465-L501","documentation":"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.","triggerScenarios":"Calling the LMArena provider with an image attachment when the generateUploadUrl action response contains no '1:'-prefixed line (raise at LMArena.py:483).","commonSituations":"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.","solutions":["Update g4f — the provider re-scrapes _next_action ids (LMArena.py:439) and newer releases track frontend builds","Supply fresh lmarena.org cookies from a logged-in session so the server action is authorized","Retry without the image to confirm text-only chat works, isolating the upload path","Check egress IP reputation if the body looks like a Cloudflare challenge"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"def has_lmarena_auth(cookies: dict) -> bool:\n    # anonymous sessions often cannot use server-action uploads\n    return any(k in cookies for k in (\"__Secure-next-auth.session-token\",))","typeGuard":null,"tryCatchPattern":"try:\n    media = await upload_image(image)\nexcept Exception as e:\n    if \"Failed to get upload URL\" in str(e):\n        media = None  # degrade gracefully: send text-only request","preventionTips":["Supply fresh logged-in lmarena.org cookies for file uploads","Keep g4f updated; action ids are re-scraped each release","Design callers to degrade to text-only when the upload path breaks"],"tags":["lmarena","nextjs","upload","image","scraping","cloudflare"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}