openai/openai-python · error · TypeError

Expected query input to be a dictionary for multipart reques

Error message

Expected query input to be a dictionary for multipart requests but got {type(json_data)} instead.

What it means

The OpenAI Python SDK raises this ValueError when await client.vector_stores.file_batches.retrieve() (async) is called with a falsy batch_id. The guard fires before the request, requiring the 'vsfb_...' batch identifier to be a non-empty string for the retrieval path.

Source

Thrown at src/openai/_base_client.py:560

        content_type = headers.get("Content-Type")
        files = options.files

        # If the given Content-Type header is multipart/form-data then it
        # has to be removed so that httpx can generate the header with
        # additional information for us as it has to be in this form
        # for the server to be able to correctly parse the request:
        # multipart/form-data; boundary=---abc--
        if content_type is not None and content_type.startswith("multipart/form-data"):
            if "boundary" not in content_type:
                # only remove the header if the boundary hasn't been explicitly set
                # as the caller doesn't want httpx to come up with their own boundary
                headers.pop("Content-Type")

            # As we are now sending multipart/form-data instead of application/json
            # we need to tell httpx to use it, https://www.python-httpx.org/advanced/clients/#multipart-file-encoding
            if json_data:
                if not is_dict(json_data):
                    raise TypeError(
                        f"Expected query input to be a dictionary for multipart requests but got {type(json_data)} instead."
                    )
                kwargs["data"] = self._serialize_multipartform(json_data)

            # httpx determines whether or not to send a "multipart/form-data"
            # request based on the truthiness of the "files" argument.
            # This gets around that issue by generating a dict value that
            # evaluates to true.
            #
            # https://github.com/encode/httpx/discussions/2399#discussioncomment-3814186
            if not files:
                files = cast(HttpxRequestFiles, ForceMultipartDict())

        prepared_url = self._prepare_url(options.url)
        # preserve hard-coded query params from the url
        if params and prepared_url.query:
            params = {**dict(prepared_url.params.items()), **params}
            prepared_url = prepared_url.copy_with(raw_path=prepared_url.raw_path.split(b"?", 1)[0])

View on GitHub (pinned to 9917c6e28e)

Solutions

  1. Capture the batch from creation and pass batch.id: batch = await client.vector_stores.file_batches.create(...); await ...retrieve(vector_store_id=vs, batch_id=batch.id).
  2. Persist batch IDs durably if your process may restart between creating and retrieving.
  3. Double-check attribute names on response objects (id, not batch_id or file_batch_id).

Example fix

# before
batch = await client.vector_stores.file_batches.retrieve(vector_store_id=vs, batch_id="")

# after
created = await client.vector_stores.file_batches.create(vector_store_id=vs, file_ids=[f.id])
batch = await client.vector_stores.file_batches.retrieve(vector_store_id=vs, batch_id=created.id)
Defensive patterns

Strategy: validation

Validate before calling

bid = job.get("batch_id")
if not bid:
    raise ValueError("job record is missing batch_id")
batch = await client.vector_stores.file_batches.retrieve(vector_store_id=vs, batch_id=bid)

Type guard

def is_valid_batch_id(v: object) -> bool:
    return isinstance(v, str) and v.startswith("vsfb_") and len(v) > 5

Prevention

When it happens

Trigger: Awaiting retrieve(vector_store_id='vs_...', batch_id='') or batch_id=None, such as when the batch creation response was discarded or its ID attribute was misread.

Common situations: Forgetting to store the create() result, accessing a nonexistent attribute on the response object (silently producing None), or state that lost the batch reference between runs.

Related errors


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