{"record":{"id":"1b8fa400794e8a5c","repo":"openai/openai-python","slug":"expected-query-input-to-be-a-dictionary-for-multip","errorCode":null,"errorMessage":"Expected query input to be a dictionary for multipart requests but got {type(json_data)} instead.","messagePattern":"Expected query input to be a dictionary for multipart requests but got (.+?) instead\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/openai/_base_client.py","lineNumber":560,"sourceCode":"        content_type = headers.get(\"Content-Type\")\n        files = options.files\n\n        # If the given Content-Type header is multipart/form-data then it\n        # has to be removed so that httpx can generate the header with\n        # additional information for us as it has to be in this form\n        # for the server to be able to correctly parse the request:\n        # multipart/form-data; boundary=---abc--\n        if content_type is not None and content_type.startswith(\"multipart/form-data\"):\n            if \"boundary\" not in content_type:\n                # only remove the header if the boundary hasn't been explicitly set\n                # as the caller doesn't want httpx to come up with their own boundary\n                headers.pop(\"Content-Type\")\n\n            # As we are now sending multipart/form-data instead of application/json\n            # we need to tell httpx to use it, https://www.python-httpx.org/advanced/clients/#multipart-file-encoding\n            if json_data:\n                if not is_dict(json_data):\n                    raise TypeError(\n                        f\"Expected query input to be a dictionary for multipart requests but got {type(json_data)} instead.\"\n                    )\n                kwargs[\"data\"] = self._serialize_multipartform(json_data)\n\n            # httpx determines whether or not to send a \"multipart/form-data\"\n            # request based on the truthiness of the \"files\" argument.\n            # This gets around that issue by generating a dict value that\n            # evaluates to true.\n            #\n            # https://github.com/encode/httpx/discussions/2399#discussioncomment-3814186\n            if not files:\n                files = cast(HttpxRequestFiles, ForceMultipartDict())\n\n        prepared_url = self._prepare_url(options.url)\n        # preserve hard-coded query params from the url\n        if params and prepared_url.query:\n            params = {**dict(prepared_url.params.items()), **params}\n            prepared_url = prepared_url.copy_with(raw_path=prepared_url.raw_path.split(b\"?\", 1)[0])","sourceCodeStart":542,"sourceCodeEnd":578,"githubUrl":"https://github.com/openai/openai-python/blob/9917c6e28e66e90e1227b3d223c06a8c5441515a/src/openai/_base_client.py#L542-L578","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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).","Persist batch IDs durably if your process may restart between creating and retrieving.","Double-check attribute names on response objects (id, not batch_id or file_batch_id)."],"exampleFix":"# before\nbatch = await client.vector_stores.file_batches.retrieve(vector_store_id=vs, batch_id=\"\")\n\n# after\ncreated = await client.vector_stores.file_batches.create(vector_store_id=vs, file_ids=[f.id])\nbatch = await client.vector_stores.file_batches.retrieve(vector_store_id=vs, batch_id=created.id)","handlingStrategy":"validation","validationCode":"bid = job.get(\"batch_id\")\nif not bid:\n    raise ValueError(\"job record is missing batch_id\")\nbatch = await client.vector_stores.file_batches.retrieve(vector_store_id=vs, batch_id=bid)","typeGuard":"def is_valid_batch_id(v: object) -> bool:\n    return isinstance(v, str) and v.startswith(\"vsfb_\") and len(v) > 5","tryCatchPattern":null,"preventionTips":["Persist batch IDs across process restarts.","Verify response attribute names (.id) rather than guessing."],"tags":["openai","vector-stores","file-batches","async","validation","python"],"backgroundTag":"empty-required-parameter","analyzedSha":"9917c6e28e66e90e1227b3d223c06a8c5441515a","analyzedAt":"2026-08-28T11:46:34.183Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}