langchain-ai/deepagents · error · TypeError
Offload request must be a JSON object.
Error message
Offload request must be a JSON object.
What it means
The offload API expects the request payload to be a decoded JSON object (a Python dict at the top level). Anything else — a JSON array, string, number, or undecoded raw JSON text — is rejected with this TypeError before any field is inspected. This enforces the server's wire contract that an offload request is a single object with operation_id/context/hook_responses fields.
Source
Thrown at libs/code/deepagents_code/offload_api.py:516
def _operation_payload(
payload: object,
) -> tuple[str, dict[str, Any], dict[str, object]]:
"""Validate the narrow client-to-operation request shape.
Args:
payload: Decoded request JSON.
Returns:
Operation id, runtime context, and accumulated hook responses.
Raises:
TypeError: If the payload or a structured field has the wrong shape.
"""
if not isinstance(payload, dict):
msg = "Offload request must be a JSON object."
raise TypeError(msg)
operation_id = payload.get("operation_id")
context = payload.get("context")
responses = payload.get("hook_responses", {})
if not isinstance(operation_id, str) or not operation_id:
msg = "operation_id must be a non-empty string."
raise TypeError(msg)
if not isinstance(context, dict):
msg = "context must be a JSON object."
raise TypeError(msg)
if not isinstance(responses, dict):
msg = "hook_responses must be a JSON object."
raise TypeError(msg)
validated_context = {str(key): value for key, value in context.items()}
_validate_context(validated_context)
return (
operation_id,
_strip_transport_model_params(validated_context),
{str(key): value for key, value in responses.items()},View on GitHub (pinned to a1af029e6e)
Solutions
- Decode first: payload = json.loads(raw_body) before passing it on.
- If you get bytes, use json.loads(raw) (it accepts bytes) and confirm the result is a dict.
- If you intended to send multiple operations, send them one at a time or wrap them under an object key the API defines.
- Log/inspect type(payload) to confirm you are not passing a str wrapper around an already-parsed dict.
Example fix
// before
result = await offload('{"operation_id": "op1", "context": {}}')
// after
import json
result = await offload(json.loads('{"operation_id": "op1", "context": {}}')) Defensive patterns
Strategy: type-guard
Validate before calling
import json
def ensure_object_payload(raw):
payload = json.loads(raw) if isinstance(raw, (str, bytes, bytearray)) else raw
if not isinstance(payload, dict):
raise ValueError("Offload payload must decode to a JSON object")
return payload Type guard
def is_json_object(value) -> bool:
return isinstance(value, dict) Try / catch
try:
state = await offload(thread_id, payload)
except TypeError as exc:
if "must be a JSON object" in str(exc):
state = await offload(thread_id, json.loads(payload))
else:
raise Prevention
- Always json.loads() HTTP bodies/bytes before passing them as payloads
- Never pre-serialize nested fields with json.dumps inside an already-decoded payload
- Assert isinstance(payload, dict) at the boundary of your transport layer
- Send one operation object per request, not an array
When it happens
Trigger: Calling offload() (or passing a payload into the request handling) with a JSON string like '{"operation_id": ...}' that was never json.loads()-ed, a list of operations, None, or a custom object instead of a dict.
Common situations: Double-encoded JSON from an HTTP client (body already a string), forwarding the raw request body without decoding, sending an array of requests where one object was expected, or a framework handing you a bytes body.
Related errors
- context must be a JSON object.
- operation_id must be a non-empty string.
- hook_responses must be a JSON object.
- Invalid {SERVER_ENV_PREFIX}ALLOW_FS_TOOLS value: {raw!r}; ex
- interpreter_ptc must be False, 'safe', 'all', or a list of t
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/f56751abab01703e.
Report an issue: GitHub.