aio-libs/aiohttp · error · TypeError
value argument must be byte-ish, not
Error message
value argument must be byte-ish, not {type(value)!r} What it means
Raised by BytesPayload.__init__ when the value argument is not bytes, bytearray, or memoryview. BytesPayload is the factory-selected Payload class for raw binary data, so any non-byte-ish object (most commonly a str) is rejected at construction rather than failing later during serialization. aiohttp will not implicitly encode text for you here.
Solutions
- Encode the string to bytes before passing: payload = BytesPayload(text.encode('utf-8')).
- For JSON, use session.post(url, json=obj) or JsonPayload(obj) instead of a raw bytes payload.
- For text payloads, use TextPayload or aiohttp's TextIOPayload which handle encoding via content-type charset.
Example fix
# before
payload = BytesPayload('{"k": 1}')
# after
from aiohttp.payload import JsonPayload
payload = JsonPayload({'k': 1}) Defensive patterns
Strategy: type-guard
Validate before calling
if isinstance(value, str):
value = value.encode('utf-8')
payload = BytesPayload(value) Type guard
def is_byteish(v) -> bool:
return isinstance(v, (bytes, bytearray, memoryview)) Try / catch
try:
payload = BytesPayload(value)
except TypeError:
payload = BytesPayload(str(value).encode('utf-8')) Prevention
- Encode str to bytes before building a raw payload.
- Prefer JsonPayload/TextPayload for structured or text data over BytesPayload.
- Add a unit test that feeds the expected types into payload construction.
When it happens
Trigger: Passing a str to a request body that resolves to BytesPayload, e.g. session.post(url, data='plain text') in some code paths, or constructing BytesPayload('hello') directly; passing an int, list, or None as the value.
Common situations: Sending JSON or form text without encoding; assuming aiohttp auto-encodes str the same way the high-level client does for the data= argument (the low-level BytesPayload does not); feeding a value returned by json.dumps without encode().
Related errors
- Can not serialize value type: %r headers: %r value: %r
- Cannot create payload from %r
- expected str, got
- value argument must support collections.abc.AsyncIterable…
- content_type must be an instance of str. Got
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/bb6bb310a659ab0c.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/payload.py:358
class BytesPayload(Payload):
_value: bytes
# _consumed = False (inherited) - Bytes are immutable and can be reused
_autoclose = True # No file handle, just bytes in memory
def __init__(
self, value: bytes | bytearray | memoryview, *args: Any, **kwargs: Any
) -> None:
if "content_type" not in kwargs:
kwargs["content_type"] = "application/octet-stream"
super().__init__(value, *args, **kwargs)
if isinstance(value, memoryview):
self._size = value.nbytes
elif isinstance(value, (bytes, bytearray)):
self._size = len(value)
else:
raise TypeError(f"value argument must be byte-ish, not {type(value)!r}")
if self._size > TOO_LARGE_BYTES_BODY:
warnings.warn(
"Sending a large body directly with raw bytes might"
" lock the event loop. You should probably pass an "
"io.BytesIO object instead",
ResourceWarning,
source=self,
)
def decode(self, encoding: str = "utf-8", errors: str = "strict") -> str:
return self._value.decode(encoding, errors)
async def as_bytes(self, encoding: str = "utf-8", errors: str = "strict") -> bytes:
"""
Return bytes representation of the value.
This method returns the raw bytes content of the payload.View on GitHub (pinned to d041d4d0fd)