aio-libs/aiohttp · error · TypeError
Can not serialize value type: %r headers: %r value: %r
Error message
Can not serialize value type: %r headers: %r value: %r
What it means
FormData._gen_form_data raises TypeError (wrapping the original exception) when payload.get_payload cannot find a registered payload type for a field value during multipart serialization. The error includes the value type, headers, and the value itself for diagnosis. This is the multipart counterpart of error 106.
Solutions
- Serialize complex objects before adding: form.add_field('data', json.dumps(my_dict), content_type='application/json')
- For file-like objects, wrap them in aiohttp.payload.AsyncIterablePayload or BufferedReaderPayload
- Register a custom payload type with aiohttp.payload.register_payload if you need first-class support
- Convert the value to str or bytes before adding
Example fix
# before
form.add_field('config', {'key': 'value'})
# after
import json
form.add_field('config', json.dumps({'key': 'value'}), content_type='application/json') Defensive patterns
Strategy: validation
Validate before calling
import io, json
def to_payload_value(value):
"""Convert a value to something aiohttp can serialize."""
if isinstance(value, (str, bytes, bytearray, memoryview, io.IOBase)):
return value
if isinstance(value, (dict, list)):
return json.dumps(value)
return str(value)
form.add_field('field', to_payload_value(my_value)) Type guard
import io
def is_serializable_payload(value) -> bool:
return isinstance(value, (str, bytes, bytearray, memoryview, io.IOBase)) Try / catch
try:
form.add_field('field', value)
body = form()
except TypeError as e:
if 'Can not serialize' in str(e):
# Fall back to JSON serialization
form._fields.pop()
form.add_field('field', json.dumps(value), content_type='application/json')
raise Prevention
- Never pass raw dicts, lists, or custom objects as form field values
- Pre-serialize with json.dumps() or str() before adding to FormData
- Register custom payload types for domain objects you use frequently
When it happens
Trigger: Adding a field whose value type has no registered aiohttp payload handler — e.g. a plain dict, a list, a custom Python object, or a set. Also triggered by passing an object that is not io.IOBase, bytes, str, or any type registered via payload.register_payload.
Common situations: Passing a JSON-serializable dict directly as a form field instead of serializing it first; passing a custom dataclass or ORM model instance; passing a list of values where a single value is expected.
Related errors
- Cannot create payload from %r
- content_type must be an instance of str. Got
- expected str, got
- filename must be an instance of str. Got
- Only io.IOBase, multidict and (name, file) pairs allowed…
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/69d22efdf8683a2c.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/formdata.py:143
)
def _gen_form_data(self) -> multipart.MultipartWriter:
"""Encode a list of fields using the multipart/form-data MIME format"""
for dispparams, headers, value in self._fields:
try:
if hdrs.CONTENT_TYPE in headers:
part = payload.get_payload(
value,
content_type=headers[hdrs.CONTENT_TYPE],
headers=headers,
encoding=self._charset,
)
else:
part = payload.get_payload(
value, headers=headers, encoding=self._charset
)
except Exception as exc:
raise TypeError(
"Can not serialize value type: %r\n "
"headers: %r\n value: %r" % (type(value), headers, value)
) from exc
if dispparams:
part.set_content_disposition(
"form-data", quote_fields=self._quote_fields, **dispparams
)
# FIXME cgi.FieldStorage doesn't likes body parts with
# Content-Length which were sent via chunked transfer encoding
assert part.headers is not None
part.headers.popall(hdrs.CONTENT_LENGTH, None)
self._writer.append_payload(part)
self._fields.clear()
return self._writer
View on GitHub (pinned to d041d4d0fd)