aio-libs/aiohttp · warning · HTTPExpectationFailed

Unknown Expect: %s

Error message

Unknown Expect: %s

What it means

The default Expect-header handler (_default_expect_handler) is invoked when a request carries an Expect header. For HTTP/1.1, the only recognized value is '100-continue' (case-insensitive), to which the server responds with an interim 'HTTP/1.1 100 Continue'. Any other Expect value (e.g. a future or custom expectation token) raises HTTPExpectationFailed (HTTP 417), because the server cannot satisfy an unknown expectation and per RFC 7231 must reject the request.

Source

Thrown at aiohttp/web_urldispatcher.py:305

    def __repr__(self) -> str:
        return f"<MatchInfoError {self._exception.status}: {self._exception.reason}>"


async def _default_expect_handler(request: Request) -> None:
    """Default handler for Expect header.

    Just send "100 Continue" to client.
    raise HTTPExpectationFailed if value of header is not "100-continue"
    """
    expect = request.headers.get(hdrs.EXPECT, "")
    if request.version == HttpVersion11:
        if expect.lower() == "100-continue":
            await request.writer.write(b"HTTP/1.1 100 Continue\r\n\r\n")
            # Reset output_size as we haven't started the main body yet.
            request.writer.output_size = 0
        else:
            raise HTTPExpectationFailed(text="Unknown Expect: %s" % expect)


class Resource(AbstractResource):
    def __init__(self, *, name: str | None = None) -> None:
        super().__init__(name=name)
        self._routes: dict[str, ResourceRoute] = {}
        self._any_route: ResourceRoute | None = None
        self._allowed_methods: set[str] = set()

    def add_route(
        self,
        method: str,
        handler: type[AbstractView] | Handler,
        *,
        expect_handler: _ExpectHandler | None = None,
    ) -> "ResourceRoute":
        if route := self._routes.get(method, self._any_route):
            raise RuntimeError(

View on GitHub (pinned to d041d4d0fd)

Solutions

  1. Have the client send only 'Expect: 100-continue' (the RFC-defined expectation) or omit the header.
  2. If a custom expectation is needed, register a custom expect_handler on the route via expect_handler=<async fn> that handles your token.
  3. Return a clear 417 response to the client and document the unsupported expectation.

Example fix

// before (client)
headers = {'Expect': '102-processing'}
// after
headers = {'Expect': '100-continue'}  # or omit the header
Defensive patterns

Strategy: try-catch

Try / catch

from aiohttp.web_exceptions import HTTPExpectationFailed

async def handler(request):
    try:
        ...
    except HTTPExpectationFailed:
        return web.Response(status=417, text='Unsupported Expect header')

Prevention

When it happens

Trigger: A client sends an HTTP/1.1 request with an Expect header whose value is not '100-continue' — for example 'Expect: 102-processing', a custom token, or a malformed value. The error is raised during request handling, after the request line and headers are parsed and the route is dispatched, when aiohttp invokes the expect_handler.

Common situations: Non-compliant or experimental clients; testing tools that inject arbitrary Expect values; a client library that sends a newer expectation token the server does not yet support; proxy chaining that mangles the header.

Related errors


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