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.Client` or `httpx2.Client` but got {type(http_client)}

What it means

Raised by sync upload_file_chunked when `file` is bytes and `bytes` (the declared total size) was not given. The chunked upload protocol needs the total size up front to create the upload session, and it cannot be derived from streaming bytes, so the SDK raises TypeError. In practice this fires only when filename was provided but the size is missing.

Source

Thrown at src/openai/_base_client.py:929

            # 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_sync_client(http_client)
            and not is_legacy_httpx_sync_client(http_client)
        ):
            raise TypeError(
                "Invalid `http_client` argument; Expected an instance of `httpx.Client` or `httpx2.Client` "
                f"but got {type(http_client)}"
            )

        super().__init__(
            version=version,
            # cast to a valid type because mypy doesn't understand our type narrowing
            timeout=cast(Timeout, timeout),
            base_url=base_url,
            max_retries=max_retries,
            custom_query=custom_query,
            custom_headers=custom_headers,
            _strict_response_validation=_strict_response_validation,
        )
        self._client = http_client or SyncHttpxClientWrapper(
            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. Prefer the public client.files.create / upload helper over manual chunked calls so sizes are handled for you
  2. If calling upload_file_chunked directly, always pass bytes=len(data) alongside filename
  3. Validate size is a positive int before uploading

Example fix

# before
client.beta.uploads.upload_file_chunked(data, purpose='assistants', filename='a.bin')
# after
client.uploads.upload_file_chunked(data, bytes=len(data), purpose='assistants', filename='a.bin')
Defensive patterns

Strategy: validation

Validate before calling

if isinstance(data, bytes):
    assert filename, 'filename required for bytes uploads'
    assert isinstance(total_bytes, int) and total_bytes > 0, 'bytes (size) required'

Type guard

def chunked_args_ready(data: object, filename: object, size: object) -> bool:
    return (not isinstance(data, (bytes, bytearray))) or (bool(filename) and isinstance(size, int) and size > 0)

Prevention

When it happens

Trigger: Calling upload_file_chunked with in-memory bytes, a filename, but omitting the bytes= (size) argument.

Common situations: Hand-rolling the multipart/chunked flow against uploads.create + parts.create + complete instead of using the helper, or partially migrating old code that passed only the file.

Related errors


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