aio-libs/aiohttp · error · ValueError

HTTP redirects need a location to redirect to.

Error message

HTTP redirects need a location to redirect to.

What it means

HTTPMove subclasses (HTTPMovedPermanently, HTTPFound, HTTPSeeOther, HTTPTemporaryRedirect, HTTPPermanentRedirect) require a truthy location. A 3xx redirect without a Location header is invalid HTTP, so the constructor rejects falsy locations (empty string, None, empty URL).

Source

Thrown at aiohttp/web_exceptions.py:230


############################################################
# 3xx redirection
############################################################


class HTTPMove(HTTPRedirection):
    def __init__(
        self,
        location: StrOrURL,
        *,
        headers: LooseHeaders | None = None,
        reason: str | None = None,
        text: str | None = None,
        content_type: str | None = None,
    ) -> None:
        if not location:
            raise ValueError("HTTP redirects need a location to redirect to.")
        super().__init__(
            headers=headers, reason=reason, text=text, content_type=content_type
        )
        self._location = URL(location)
        self.headers["Location"] = str(self.location)

    @property
    def location(self) -> URL:
        return self._location


class HTTPMultipleChoices(HTTPMove):
    status_code = 300


class HTTPMovedPermanently(HTTPMove):
    status_code = 301

View on GitHub (pinned to d041d4d0fd)

Solutions

  1. Validate the location is non-empty before constructing the redirect.
  2. Provide a safe fallback URL when the source is empty.
  3. Build the URL with yarl.URL and confirm it is absolute before redirecting.

Example fix

# before
target = request.query.get('next', '')
raise HTTPFound(target)
# after
target = request.query.get('next') or '/'
if not target.startswith('/'):
    target = '/'
raise HTTPFound(target)
Defensive patterns

Strategy: validation

Validate before calling

if not location:
    location = '/'
raise web.HTTPFound(location)

Type guard

def has_location(loc: object) -> TypeGuard[str | URL]:
    return bool(loc)

Prevention

When it happens

Trigger: HTTPFound(''), HTTPMovedPermanently(None), or building the location from a request header that is absent so it defaults to empty.

Common situations: Redirecting to a URL computed from Referer/next params that the client omitted; conditional redirect where the target ends up empty; passing a yarl.URL built from an empty string.

Related errors


AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11). Data as JSON: /api/errors/bcdce748af7100be. Report an issue: GitHub.