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
- Pass only data= and let dumps() produce the bytes body.
- 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
- Pass data= and a dumps= callable; let it produce the body bytes.
- Use Response(body=bytes, content_type='application/json') when you already have bytes and no encoder.
- Avoid forwarding body= into json_bytes_response wrappers.
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
- only one of data, text, or body should be specified
- body and text are not allowed together
- Method cannot contain non-token characters {method!r} (found
- Invalid Content-Length header: {content_length_hdr!r}
- compress must be one of True, False, 'deflate', or 'gzip'
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/5ed465ee6275527c.json.
Report an issue: GitHub.