encode/httpx · error · TypeError
Invalid type for value. Expected primitive type, got {type(v
Error message
Invalid type for value. Expected primitive type, got {type(value)}: {value!r} What it means
Raised as `TypeError` by `DataField.__init__` when a multipart field `value` is not one of the allowed primitive types (`str`, `bytes`, `int`, `float`, or `None`). Multipart form values must serialize to bytes; arbitrary objects (lists, dicts, custom classes) cannot be sent as plain form fields and are rejected.
Source
Thrown at httpx/_multipart.py:81
if b";" in content_type:
for section in content_type.split(b";"):
if section.strip().lower().startswith(b"boundary="):
return section.strip()[len(b"boundary=") :].strip(b'"')
return None
class DataField:
"""
A single form field item, within a multipart form field.
"""
def __init__(self, name: str, value: str | bytes | int | float | None) -> None:
if not isinstance(name, str):
raise TypeError(
f"Invalid type for name. Expected str, got {type(name)}: {name!r}"
)
if value is not None and not isinstance(value, (str, bytes, int, float)):
raise TypeError(
"Invalid type for value. Expected primitive type,"
f" got {type(value)}: {value!r}"
)
self.name = name
self.value: str | bytes = (
value if isinstance(value, bytes) else primitive_value_to_str(value)
)
def render_headers(self) -> bytes:
if not hasattr(self, "_headers"):
name = _format_form_param("name", self.name)
self._headers = b"".join(
[b"Content-Disposition: form-data; ", name, b"\r\n\r\n"]
)
return self._headers
def render_data(self) -> bytes:View on GitHub (pinned to b5addb64f0)
Solutions
- Send structured data as JSON: `client.post(url, json=payload)` instead of `data=payload`.
- If the API expects a stringified field, serialize first: `data={'opts': ','.join(opts)}` or `json.dumps(value)`.
- Flatten nested structures into multiple `key[]`-style field names if the server expects repeated form fields.
- Add a pre-flight type check on each value.
Example fix
// before
client.post(url, data={'filters': {'a': 1}}) # TypeError
// after
client.post(url, json={'filters': {'a': 1}}) Defensive patterns
Strategy: validation
Validate before calling
ALLOWED = (str, bytes, int, float, type(None))
def validate_form_values(data: dict) -> None:
bad = {k: type(v).__name__ for k, v in data.items()
if not isinstance(v, ALLOWED)}
if bad:
raise TypeError(f'non-primitive form values: {bad}') Type guard
def form_values_are_primitive(data: dict) -> bool:
return all(
v is None or isinstance(v, (str, bytes, int, float))
for v in data.values()
) Try / catch
try:
client.post(url, data=payload)
except TypeError:
# structured payload - send as JSON instead
client.post(url, json=payload) Prevention
- Send nested/structured data via json=, not data=.
- Serialize lists/dicts to strings explicitly when the API truly wants a form field.
- Validate each value type before building the multipart payload.
When it happens
Trigger: Passing `data={'opt': ['a','b']}` or `data={'obj': some_object}` to `client.post(url, data=...)`; using a dict-of-dicts where each value is structured rather than scalar.
Common situations: Confusing form fields with JSON bodies — passing nested data to `data=` instead of `json=`; forgetting to `json.dumps` a list before putting it in a form field; serializing ORM objects naively.
Related errors
- Invalid type for name. Expected str, got {type(name)}: {name
- Multipart file uploads require 'io.BytesIO', not 'io.StringI
- Multipart file uploads must be opened in binary mode, not te
- Invalid "auth" argument: {auth!r}
- Attempted to read or stream content, but the stream has been
AI-assisted analysis of encode/httpx@b5addb64f0 (2026-08-04).
Data as JSON: /data/errors/f4ff5a851445cf94.json.
Report an issue: GitHub.