aio-libs/aiohttp · error · InvalidUrlRedirectClientError
Invalid redirect URL origin
Error message
Invalid redirect URL origin
What it means
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.
Source
Thrown at aiohttp/client.py:836
"Server attempted redirecting to a location that does not look like a URL",
) from e
scheme = parsed_redirect_url.scheme
if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:
if req._body is not None:
await req._body.close()
resp.close()
raise NonHttpUrlRedirectClientError(r_url)
elif not scheme:
parsed_redirect_url = url.join(parsed_redirect_url)
try:
redirect_origin = parsed_redirect_url.origin()
except ValueError as origin_val_err:
if req._body is not None:
await req._body.close()
resp.close()
raise InvalidUrlRedirectClientError(
parsed_redirect_url,
"Invalid redirect URL origin",
) from origin_val_err
if url.origin() != redirect_origin:
cookies = None
headers.popall(hdrs.AUTHORIZATION, None)
headers.popall(hdrs.COOKIE, None)
headers.popall(hdrs.PROXY_AUTHORIZATION, None)
url = parsed_redirect_url
params = {}
resp.release()
continue
break
if req._body is not None:View on GitHub (pinned to c0ef574e29)
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).
Example fix
// before resp = await session.get(url) # Location = '//cdn/x' with no scheme -> raise // after from yarl import URL resp = await session.get(url, allow_redirects=False) loc = URL(resp.headers['Location']).origin() # validate first resp = await session.get(loc)
Defensive patterns
Strategy: validation
Validate before calling
from yarl import URL
def valid_redirect_origin(loc: str, base: str) -> bool:
try:
joined = URL(base).join(URL(loc))
_ = joined.origin()
return True
except ValueError:
return False Try / catch
from aiohttp import InvalidUrlRedirectClientError
try:
resp = await session.get(url)
except InvalidUrlRedirectClientError as e:
if 'origin' in str(e):
resp = await session.get(url, allow_redirects=False)
else:
raise Prevention
- 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.
When it happens
Trigger: 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()`.
Common situations: 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.
Related errors
- Server attempted redirecting to a location that does not loo
- base_url must have a trailing '/'
- Cannot combine AUTHORIZATION header with credentials encoded
- Cannot follow redirect with a consumed request body. Use byt
- Invalid response status
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/ca754169e78f43d9.json.
Report an issue: GitHub.