{"id":"ca754169e78f43d9","repo":"aio-libs/aiohttp","slug":"invalid-redirect-url-origin","errorCode":null,"errorMessage":"Invalid redirect URL origin","messagePattern":"Invalid redirect URL origin","errorType":"exception","errorClass":"InvalidUrlRedirectClientError","httpStatus":null,"severity":"error","filePath":"aiohttp/client.py","lineNumber":836,"sourceCode":"                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            if req._body is not None:\n                                await req._body.close()\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            if req._body is not None:\n                                await req._body.close()\n                            resp.close()\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            cookies = None\n                            headers.popall(hdrs.AUTHORIZATION, None)\n                            headers.popall(hdrs.COOKIE, None)\n                            headers.popall(hdrs.PROXY_AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            if req._body is not None:","sourceCodeStart":818,"sourceCodeEnd":854,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/client.py#L818-L854","documentation":"Raised as `InvalidUrlRedirectClientError` (client.py:830-839) when the parsed redirect URL parses but `yarl.URL.origin()` raises `ValueError` — typically because the URL has no scheme/host (e.g., a scheme-relative `//host/path` whose scheme couldn't be joined, or a host-less path that joined incorrectly). Distinct from error 48 (unparseable) and from `NonHttpUrlRedirectClientError` (non-http scheme): here the URL object exists but lacks a computable origin.","triggerScenarios":"Server returns `Location: ///path` (triple slash, no host), `Location: file:///x`, or a relative URL that failed to join against the request URL into something with a scheme+host. The code path joins relative URLs at client.py:828, then attempts `.origin()`.","commonSituations":"Buggy server returning a Location with no host; client followed a redirect chain that ended on a misconfigured vhost; reverse proxy stripped the host; scheme-relative URLs (`//cdn`) when the base URL itself is malformed.","solutions":["Use `allow_redirects=False` and manually resolve/validate the Location against the request URL.","Fix the server-side redirect so Location is an absolute URL with scheme and host.","Verify the request URL itself isn't malformed (a bad base URL propagates into a bad join)."],"exampleFix":"// before\nresp = await session.get(url)  # Location = '//cdn/x' with no scheme -> raise\n// after\nfrom yarl import URL\nresp = await session.get(url, allow_redirects=False)\nloc = URL(resp.headers['Location']).origin()  # validate first\nresp = await session.get(loc)","handlingStrategy":"validation","validationCode":"from yarl import URL\n\ndef valid_redirect_origin(loc: str, base: str) -> bool:\n    try:\n        joined = URL(base).join(URL(loc))\n        _ = joined.origin()\n        return True\n    except ValueError:\n        return False","typeGuard":null,"tryCatchPattern":"from aiohttp import InvalidUrlRedirectClientError\n\ntry:\n    resp = await session.get(url)\nexcept InvalidUrlRedirectClientError as e:\n    if 'origin' in str(e):\n        resp = await session.get(url, allow_redirects=False)\n    else:\n        raise","preventionTips":["Validate Location produces a URL with scheme+host before following.","Disable auto-redirect on untrusted upstreams.","Test redirect chains against your real server in CI."],"tags":["client","redirect","url","origin","server-misbehavior"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}