aio-libs/aiohttp · error · TypeError

value argument must be byte-ish, not {type(value)!r}

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 an instance of bytes, bytearray, or memoryview. BytesPayload is strictly for binary buffer types; any other type (str, int, list, etc.) is rejected because it cannot be written as raw octets.

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

Solutions

  1. Encode strings first: `BytesPayload(my_str.encode('utf-8'))`, or use StringPayload for str.
  2. Ensure the value is bytes/bytearray/memoryview before constructing the payload.
  3. For JSON data use JsonPayload; for arbitrary objects convert to bytes explicitly.

Example fix

// before
BytesPayload('hello')  # str -> TypeError
// after
BytesPayload(b'hello')
# or
BytesPayload('hello'.encode('utf-8'))
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(value, (bytes, bytearray, memoryview)):
    raise TypeError('BytesPayload requires bytes/bytearray/memoryview')

Type guard

def is_byteish(value) -> bool:
    return isinstance(value, (bytes, bytearray, memoryview))

Try / catch

try:
    payload = BytesPayload(value)
except TypeError:
    payload = BytesPayload(str(value).encode('utf-8'))

Prevention

When it happens

Trigger: Constructing `BytesPayload(value)` directly, or indirectly by passing a non-byte object to an API that routes to BytesPayload (e.g. `data=<str>` where the registry selects BytesPayload, or explicit instantiation with a str).

Common situations: Passing a Python str instead of bytes; passing an int/None/list; a function that sometimes returns str and sometimes bytes; encoding a str without `.encode()`.

Related errors


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