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

  1. Serialize complex objects before adding: form.add_field('data', json.dumps(my_dict), content_type='application/json')
  2. For file-like objects, wrap them in aiohttp.payload.AsyncIterablePayload or BufferedReaderPayload
  3. Register a custom payload type with aiohttp.payload.register_payload if you need first-class support
  4. 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

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


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)