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

Raised by FormData._gen_form_data (multipart path) wrapping any exception from payload.get_payload in a TypeError. It means none of aiohttp's registered Payload subclasses could handle the value type for the given headers/content_type. The message echoes type(value), headers, and value to aid diagnosis.

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 c0ef574e29)

Solutions

  1. Convert the value to a supported type (str/bytes/IOBase) before add_field.
  2. For JSON, pass json.dumps(obj) as a str with content_type='application/json'.
  3. Register a custom payload with payload.register_payload if you need a reusable adapter.

Example fix

// before
form.add_field('data', {'a': 1}, content_type='application/json')
// after
import json
form.add_field('data', json.dumps({'a': 1}), content_type='application/json')
Defensive patterns

Strategy: validation

Validate before calling

import json
value = {'a': 1}
serialized = json.dumps(value) if isinstance(value, (dict, list)) else value
form.add_field('data', serialized, content_type='application/json')

Type guard

import io
from aiohttp.payload import PAYLOAD_REGISTRY
def is_supported_payload_value(v) -> bool:
    return isinstance(v, (str, bytes, bytearray, memoryview, io.IOBase))

Try / catch

try:
    form.add_field('data', value, content_type=ct)
except TypeError:
    form.add_field('data', json.dumps(value), content_type='application/json')

Prevention

When it happens

Trigger: Appending a field whose value is an arbitrary Python object (e.g. a dict, custom class, or set) with no registered payload handler in multipart mode. Also passing a bytes-like with an unsupported content_type that bypasses defaults.

Common situations: Trying to JSON-serialize by passing a raw dict instead of json.dumps(...); passing a custom object without registering a Payload family; passing a memoryview with a content_type that has no payload adapter.

Related errors


AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04). Data as JSON: /data/errors/69d22efdf8683a2c.json. Report an issue: GitHub.