encode/httpx · error · TypeError
Invalid type for name. Expected str, got {type(name)}: {name
Error message
Invalid type for name. Expected str, got {type(name)}: {name!r} What it means
Raised as `TypeError` by `DataField.__init__` when the multipart field `name` is not a `str`. Multipart form field names must be text (they become the `name=` parameter in the `Content-Disposition` header), so passing bytes, an int, or None for the field name is rejected up front.
Source
Thrown at httpx/_multipart.py:77
if not content_type or not content_type.startswith(b"multipart/form-data"):
return None
# parse boundary according to
# https://www.rfc-editor.org/rfc/rfc2046#section-5.1.1
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"]
)View on GitHub (pinned to b5addb64f0)
Solutions
- Coerce keys to str before passing: `{str(k): v for k, v in data.items()}`.
- Validate the data dict shape before the request: `assert all(isinstance(k, str) for k in data)`.
- Convert enums: `data = {k.value: v for k, v in data.items()}` if keys are enums.
- Avoid mixing the same dict for JSON (which may allow non-string keys after encoding) and multipart.
Example fix
// before
client.post(url, data={user_id: 'on'}) # user_id is int -> TypeError
// after
client.post(url, data={str(user_id): 'on'}) Defensive patterns
Strategy: validation
Validate before calling
def normalize_form_keys(data: dict) -> dict:
bad = [k for k in data if not isinstance(k, str)]
if bad:
raise TypeError(f'non-str form field keys: {bad!r}')
return {str(k): v for k, v in data.items()} Type guard
def form_keys_are_str(data: dict) -> bool:
return all(isinstance(k, str) for k in data) Try / catch
try:
client.post(url, data=payload)
except TypeError:
payload = {str(k): v for k, v in payload.items()}
client.post(url, data=payload) Prevention
- Coerce all form-data keys to str before the request.
- Convert enum/non-str keys explicitly when building the payload.
- Keep JSON-body dicts and form-data dicts separate to avoid key-type confusion.
When it happens
Trigger: Building `data={123: 'value'}` (int key) or `data={b'key': 'value'}` (bytes key) and passing it to `client.post(url, data=..., files=...)`; or constructing `httpx._multipart.DataField(123, 'v')` directly.
Common situations: Keys coming from JSON/dict sources that use non-string keys; dataclasses/enums used as dict keys without conversion; porting code that accidentally iterates `items()` of a non-string-keyed mapping.
Related errors
- Invalid type for value. Expected primitive type, got {type(v
- 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}
- Unexpected type for 'content', {type(content)!r}
AI-assisted analysis of encode/httpx@b5addb64f0 (2026-08-04).
Data as JSON: /data/errors/3e10be3f07ab44f8.json.
Report an issue: GitHub.