openai/openai-python · error · TypeError

Invalid `http_client` argument; Expected an instance of `htt

Error message

Invalid `http_client` argument; Expected an instance of `httpx.AsyncClient` or `httpx2.AsyncClient` but got {type(http_client)}

What it means

The async client validates that a user-supplied `http_client` is an `httpx.AsyncClient` (legacy) or `httpx2.AsyncClient`. Any other object — including a sync `httpx.Client`, a wrapper, or a mock — is rejected with this TypeError at construction time.

Source

Thrown at src/openai/_base_client.py:1551

            # if the user passed in a custom http client with a non-default
            # timeout set then we use that timeout.
            #
            # note: there is an edge case here where the user passes in a client
            # where they've explicitly set the timeout to match the default timeout
            # as this check is structural, meaning that we'll think they didn't
            # pass in a timeout and will ignore it
            client_timeout = normalize_httpx_timeout(http_client.timeout) if http_client else None
            if http_client and client_timeout != HTTPX_DEFAULT_TIMEOUT:
                timeout = client_timeout
            else:
                timeout = DEFAULT_TIMEOUT

        if (
            http_client is not None
            and not is_httpx2_async_client(http_client)
            and not is_legacy_httpx_async_client(http_client)
        ):
            raise TypeError(
                "Invalid `http_client` argument; Expected an instance of `httpx.AsyncClient` or "
                f"`httpx2.AsyncClient` but got {type(http_client)}"
            )

        super().__init__(
            version=version,
            base_url=base_url,
            # cast to a valid type because mypy doesn't understand our type narrowing
            timeout=cast(Timeout, timeout),
            max_retries=max_retries,
            custom_query=custom_query,
            custom_headers=custom_headers,
            _strict_response_validation=_strict_response_validation,
        )
        self._client = http_client or AsyncHttpxClientWrapper(
            base_url=base_url,
            # cast to a valid type because mypy doesn't understand our type narrowing
            timeout=cast(Timeout, timeout),

View on GitHub (pinned to 9917c6e28e)

Solutions

  1. Pass an async client instance: `httpx2.AsyncClient(...)` or `httpx.AsyncClient(...)`
  2. For sync `OpenAI`, pass `httpx.Client`/`httpx2.Client` instead
  3. In tests, subclass `httpx2.AsyncClient` or use a mock that passes `isinstance` checks

Example fix

# before
client = AsyncOpenAI(http_client=httpx2.Client(...))  # sync!

# after
client = AsyncOpenAI(http_client=httpx2.AsyncClient(...))
Defensive patterns

Strategy: type-guard

Type guard

import httpx, httpx2

def is_acceptable_async_client(c: object) -> bool:
    return isinstance(c, (httpx.AsyncClient, httpx2.AsyncClient))

assert is_acceptable_async_client(http_client), 'http_client must be an async httpx client'

Try / catch

try:
    client = AsyncOpenAI(http_client=http_client)
except TypeError as e:
    if 'http_client' in str(e):
        raise ValueError('Provide an httpx.AsyncClient/httpx2.AsyncClient instance') from e
    raise

Prevention

When it happens

Trigger: Passing a sync `httpx.Client` to `AsyncOpenAI(http_client=...)`; passing a custom wrapper/protocol object; passing an `httpx2.Client` (sync) or a mocked client that lacks the expected base classes.

Common situations: Copy-pasting sync-client setup into async code; test doubles/fakes that subclass nothing; version drift after the SDK moved to httpx2 while user code still passes old-style clients of the wrong type.

Related errors


AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28). Data as JSON: /api/errors/8e6f81c6a272cd3f. Report an issue: GitHub.