openai/openai-python · error · TypeError

Passing both `body` and `content` is not supported

Error message

Passing both `body` and `content` is not supported

What it means

Same guard as the sync variant, but in async upload_file_chunked: when `file` is raw bytes and `filename` is None, the SDK cannot name the multipart part and raises TypeError before creating the upload session. anyio.Path inputs get their .name inferred; bytes do not.

Source

Thrown at src/openai/_base_client.py:1355

        files: RequestFiles | None = None,
        stream: bool,
        stream_cls: type[_StreamT] | None = None,
    ) -> ResponseT | _StreamT: ...

    def post(
        self,
        path: str,
        *,
        cast_to: Type[ResponseT],
        body: Body | None = None,
        content: BinaryTypes | None = None,
        options: RequestOptions = {},
        files: RequestFiles | None = None,
        stream: bool = False,
        stream_cls: type[_StreamT] | None = None,
    ) -> ResponseT | _StreamT:
        if body is not None and content is not None:
            raise TypeError("Passing both `body` and `content` is not supported")
        if files is not None and content is not None:
            raise TypeError("Passing both `files` and `content` is not supported")
        if isinstance(body, bytes):
            warnings.warn(
                "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
                "Please pass raw bytes via the `content` parameter instead.",
                DeprecationWarning,
                stacklevel=2,
            )
        opts = FinalRequestOptions.construct(
            method="post", url=path, json_data=body, content=content, files=to_httpx_files(files), **options
        )
        return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))

    def patch(
        self,
        path: str,
        *,

View on GitHub (pinned to 9917c6e28e)

Solutions

  1. Pass filename explicitly for bytes input
  2. Or pass a (anyio) Path so the name is inferred
  3. Use a meaningful extension matching the content type

Example fix

# before
await client.uploads.upload_file_chunked(img_bytes, purpose='assistants')
# after
await client.uploads.upload_file_chunked(img_bytes, purpose='assistants', filename='chart.png')
Defensive patterns

Strategy: type-guard

Validate before calling

if isinstance(data, bytes) and not filename:
    raise ValueError('filename is required for in-memory uploads')
await client.uploads.upload_file_chunked(data, purpose='assistants', filename=filename)

Type guard

def needs_filename(file: object) -> bool:
    return isinstance(file, (bytes, bytearray))

Prevention

When it happens

Trigger: Awaiting client.uploads.upload_file_chunked(b'...', purpose='assistants') without filename=; passing bytes from memory in async code.

Common situations: Async pipelines generating documents/images in memory, or porting sync path-based code to async without adding the filename argument.

Related errors


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