aio-libs/aiohttp · error · ValueError

only one of data or body should be specified

Error message

only one of data or body should be specified

What it means

json_bytes_response() is for bytes-returning encoders (e.g. orjson). It serializes `data` into body via dumps(). Passing both data= and body= is contradictory — dumps() already produces the body. The guard at lines 780-782 rejects it.

Source

Thrown at aiohttp/web_response.py:782

def json_bytes_response(
    data: Any = sentinel,
    *,
    dumps: JSONBytesEncoder,
    body: bytes | None = None,
    status: int = 200,
    reason: str | None = None,
    headers: LooseHeaders | None = None,
    content_type: str = "application/json",
) -> Response:
    """Create a JSON response using a bytes-returning encoder.

    Use this when your JSON encoder (like orjson) returns bytes
    instead of str, avoiding the encode/decode overhead.
    """
    if data is not sentinel:
        if body is not None:
            raise ValueError("only one of data or body should be specified")
        else:
            body = dumps(data)
    return Response(
        body=body,
        status=status,
        reason=reason,
        headers=headers,
        content_type=content_type,
    )

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Pass only data= and let dumps() produce the bytes body.
  2. If you already have serialized bytes and no encoder, use Response(body=bytes, content_type='application/json').

Example fix

# before
resp = json_bytes_response(data=obj, dumps=orjson.dumps, body=orjson.dumps(obj))  # raises ValueError

# after
resp = json_bytes_response(data=obj, dumps=orjson.dumps)
Defensive patterns

Strategy: validation

Validate before calling

def safe_json_bytes_response(data=sentinel, *, body=None, dumps=None, **kw):
    if data is not sentinel and body is not None:
        raise ValueError('pass only one of data or body')
    from aiohttp import json_bytes_response
    return json_bytes_response(data=data, body=body, dumps=dumps, **kw)

Prevention

When it happens

Trigger: Calling json_bytes_response(data=obj, dumps=orjson.dumps, body=b'...'). data is 'set' when not the sentinel.

Common situations: Migrating from json_response and leaving a body= kwarg; pre-caching serialized bytes and passing both.

Related errors


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