openai/openai-python · error · TypeError
Multipart field {name!r} must be a string
Error message
Multipart field {name!r} must be a string What it means
Fields listed in the multipart encodings map with as_json=False must be plain strings so they can be UTF-8 encoded as form parts. If such a field holds a non-string (int, dict, list, None), encoding is impossible and TypeError is raised naming the field.
Source
Thrown at src/openai/_multipart.py:45
# Explicit null remains a JSON part; only an omitted field selects the raw body.
if not existing_files and raw_body_field is not None and set(merged) == {raw_body_field}:
value = merged[raw_body_field]
if not isinstance(value, str):
raise TypeError("Raw multipart alternative must be a string")
return None, None, value.encode("utf-8"), encodings[raw_body_field][0]
files: list[tuple[str, FileTypes]] = list(
existing_files.items() if isinstance(existing_files, Mapping) else (existing_files or [])
)
for name, (content_type, as_json) in encodings.items():
if name not in merged:
continue
value = merged.pop(name)
if as_json:
data = openapi_dumps(value)
else:
if not isinstance(value, str):
raise TypeError(f"Multipart field {name!r} must be a string")
data = value.encode("utf-8")
files.append((name, (None, data, content_type)))
return merged or None, files, None, "multipart/form-data"
View on GitHub (pinned to 9917c6e28e)
Solutions
- Convert the value to a string before the call (str(value), or json.dumps for structured data if the field accepts JSON text)
- Move structured data into a field designed for JSON encoding or into extra_body
- Check the endpoint's parameter type and match it
Example fix
// before
client.foo.create(text_field={"a": 1})
# or
client.foo.create(text_field=42)
// after
client.foo.create(text_field=json.dumps({"a": 1}))
# or
client.foo.create(text_field="42") Defensive patterns
Strategy: type-guard
Validate before calling
payload = {k: (v if isinstance(v, str) or k in JSON_FIELDS else json.dumps(v)) for k, v in payload.items()} Type guard
from typing import TypeGuard
def all_text_fields_str(fields: dict[str, object], text_fields: set[str]) -> TypeGuard[dict[str, str]]:
return all(isinstance(fields.get(k), str) for k in text_fields) Prevention
- Match each multipart field's value type to the endpoint schema
- Coerce numbers/bools to strings before sending text-encoded fields
When it happens
Trigger: A multipart request where a text-encoded field (declared string in the API schema) receives a non-string value — e.g. passing metadata as a dict to a field the SDK encodes as text, or an int where a string enum is expected.
Common situations: Passing numbers/booleans/dicts to string-typed multipart parameters; forgetting that only as_json fields accept structured values.
Related errors
- Raw multipart alternative must be a string
- Multipart request body must be a mapping
- Multipart extra_body must be a mapping
- Expected custom parse type to be a subclass of {Stream} or {
- Pagination is only supported with mappings
AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28).
Data as JSON: /api/errors/1ac8664ed91da206.
Report an issue: GitHub.