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

  1. Use `allow_redirects=False` and manually resolve/validate the Location against the request URL.
  2. Fix the server-side redirect so Location is an absolute URL with scheme and host.
  3. 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

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


AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04). Data as JSON: /data/errors/ca754169e78f43d9.json. Report an issue: GitHub.