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
- Pass an async client instance: `httpx2.AsyncClient(...)` or `httpx.AsyncClient(...)`
- For sync `OpenAI`, pass `httpx.Client`/`httpx2.Client` instead
- 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
- Name sync and async clients distinctly (http_client vs async_http_client) to avoid mix-ups
- Lint for `httpx2.Client` being passed where an async client is expected in async functions
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
- max_retries cannot be None. If you want to disable retries,
- Unexpected JSON data type, {type(json_data)}, cannot merge w
- Expected query input to be a dictionary for multipart reques
- Passing both `content` and `json_data` is not supported
- Passing both `body` and `content` is not supported
AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28).
Data as JSON: /api/errors/8e6f81c6a272cd3f.
Report an issue: GitHub.