aio-libs/aiohttp · error · TypeError
Cannot create payload from %r
Error message
Cannot create payload from %r
What it means
Raised by MultipartWriter.append() when get_payload() cannot find any registered Payload factory for the given object type (it raises LookupError, which append converts to TypeError). The payload registry only knows a fixed set of types (bytes, str, IO, JSON-serializable, etc.); anything else cannot be turned into a body part.
Source
Thrown at aiohttp/multipart.py:1006
return '"' + quoted_value_content.decode("ascii") + '"'
@property
def boundary(self) -> str:
return self._boundary.decode("ascii")
def append(self, obj: Any, headers: Mapping[str, str] | None = None) -> Payload:
if headers is None:
headers = CIMultiDict()
if isinstance(obj, Payload):
obj.headers.update(headers)
return self.append_payload(obj)
else:
try:
payload = get_payload(obj, headers=headers)
except LookupError:
raise TypeError("Cannot create payload from %r" % obj)
else:
return self.append_payload(payload)
def append_payload(self, payload: Payload) -> Payload:
"""Adds a new body part to multipart writer."""
encoding: str | None = None
te_encoding: str | None = None
if self._is_form_data:
# https://datatracker.ietf.org/doc/html/rfc7578#section-4.7
# https://datatracker.ietf.org/doc/html/rfc7578#section-4.8
assert (
not {CONTENT_ENCODING, CONTENT_LENGTH, CONTENT_TRANSFER_ENCODING}
& payload.headers.keys()
)
# Set default Content-Disposition in case user doesn't create one
if CONTENT_DISPOSITION not in payload.headers:
name = f"section-{len(self._parts)}"
payload.set_content_disposition("form-data", name=name)View on GitHub (pinned to c0ef574e29)
Solutions
- Convert the object to a supported type first: `writer.append_json(obj)`, or `writer.append(str(obj))`, or `writer.append(bytes(obj))`.
- Wrap it in an explicit Payload subclass (e.g. JsonPayload, BytesPayload) and pass that.
- Register a custom payload factory with @payload_type for your class if you append it frequently.
Example fix
// before
writer.append(42) # int has no factory -> TypeError
// after
writer.append_json({'value': 42})
Defensive patterns
Strategy: type-guard
Validate before calling
from aiohttp.payload import PAYLOAD_REGISTRY_FACTORY_TYPES # conceptual
supported = (bytes, bytearray, memoryview, str, dict, list, tuple, io.IOBase)
if not isinstance(obj, supported):
raise TypeError(f'no payload factory for {type(obj)}') Type guard
def has_payload_factory(obj) -> bool:
from aiohttp.payload import get_payload
try:
get_payload(obj)
return True
except LookupError:
return False Try / catch
try:
writer.append(obj)
except TypeError:
writer.append_json(obj) # or str(obj) / bytes(obj) Prevention
- Convert custom objects to bytes/str/JSON before appending.
- Use append_json() for dict/list data, not bare append().
- Register a @payload_type factory for classes you append often.
When it happens
Trigger: Calling `writer.append(obj)` where obj is a type with no registered payload factory — e.g. an int, a custom dataclass instance, a dict passed where a JSON/Bytes payload was expected, or None.
Common situations: Appending a bare number, a non-serializable object, or a custom class without first converting it to bytes/str/JSON; forgetting to use append_json() for dict/list data; passing a Payload subclass that isn't registered.
Related errors
- filename must be an instance of str. Got: %s
- content_type must be an instance of str. Got: %s
- Only io.IOBase, multidict and (name, file) pairs allowed, us
- Can not serialize value type: %r headers: %r value: %r
- Unable to decode.
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/6c0f73863974ab77.json.
Report an issue: GitHub.