aio-libs/aiohttp · error · InvalidUrlRedirectClientError
Server attempted redirecting to a location that does not…
Error message
Server attempted redirecting to a location that does not look like a URL
What it means
Raised as InvalidUrlRedirectClientError when yarl.URL() raises ValueError parsing the server-supplied redirect target (LOCATION/URI header). The redirect target is structurally not a URL and cannot be followed.
Solutions
- Set allow_redirects=False and follow redirects manually so you can sanitize the LOCATION header.
- Fix or report the server returning the malformed redirect.
- If requote_redirect_url is the cause, set ClientSession(requote_redirect_url=False) (or True) to match the server's encoding convention.
Example fix
// before
await session.get(url) # server returns malformed LOCATION -> raises
// after
resp = await session.get(url, allow_redirects=False)
if 300 <= resp.status < 400:
next_url = URL(resp.headers['LOCATION'].strip())
resp = await session.get(next_url) Defensive patterns
Strategy: try-catch
Validate before calling
from aiohttp import URL
from aiohttp.client_exceptions import InvalidURL
def safe_redirect_target(raw):
try:
return URL(raw, encoded=False)
except ValueError:
return None Type guard
from aiohttp import URL
def is_valid_redirect_target(raw) -> bool:
try:
URL(raw)
return True
except ValueError:
return False Try / catch
from aiohttp.client_exceptions import InvalidUrlRedirectClientError
try:
resp = await session.get(url)
except InvalidUrlRedirectClientError as e:
# disable auto-follow and decide manually
resp = await session.get(url, allow_redirects=False) Prevention
- Validate server-supplied LOCATION values before following.
- Use allow_redirects=False for clients that must not auto-trust server URLs.
- Log redirect targets at the boundary for quick diagnosis.
When it happens
Trigger: Server returns a 3xx with a LOCATION header containing characters/syntax yarl cannot parse (control chars, malformed quoting, illegal percent-encoding). self._requote_redirect_url changes the encoded= flag passed to URL().
Common situations: Misconfigured or hostile server returning garbage LOCATION headers. Buggy server-side URL builders. Encoded vs raw redirect URL mismatch when requote_redirect_url is disabled.
Related errors
- Invalid redirect URL origin
- Cannot follow redirect with a consumed request body. Use…
- HTTP redirects need a location to redirect to.
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/6cf422060ac3f4c0.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/client.py:824
hdrs.URI
)
if r_url is None:
# see github.com/aio-libs/aiohttp/issues/2022
break
else:
# reading from correct redirection
# response is forbidden
resp.release()
try:
parsed_redirect_url = URL(
r_url, encoded=not self._requote_redirect_url
)
except ValueError as e:
if req._body is not None:
await req._body.close()
resp.close()
raise InvalidUrlRedirectClientError(
r_url,
"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()View on GitHub (pinned to d041d4d0fd)