langchain-ai/deepagents · error · TypeError

context must be a JSON object.

Error message

context must be a JSON object.

What it means

The request's `context` field must be a JSON object (dict); it carries per-operation settings like model_context_limit, auto_approve, and hooks_server_events that get validated next by _validate_context. A non-dict context (list, string, null, missing -> None) is rejected before those per-field checks.

Source

Thrown at libs/code/deepagents_code/offload_api.py:525

    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()},
    )


def _hydrate_state(values: object) -> _OffloadState:
    """Hydrate serialized checkpoint messages for the compaction service.

    Args:
        values: State values returned by LangGraph Server.

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Pass {} when there is no context instead of omitting the key or passing None.
  2. If context is a JSON string, decode it: context = json.loads(context_str) and confirm it is a dict.
  3. Ensure settings sit under the context key, not at the payload top level (typo check).
  4. Default at construction: payload['context'] = context or {}.

Example fix

// before
payload = {"operation_id": "op1"}  # context missing -> None
// after
payload = {"operation_id": "op1", "context": {}}
Defensive patterns

Strategy: validation

Validate before calling

def ensure_context(payload):
    if not isinstance(payload.get("context"), dict):
        payload["context"] = {}
    return payload

Type guard

def has_valid_context(payload) -> bool:
    return isinstance(payload.get("context"), dict)

Try / catch

try:
    state = await offload(thread_id, payload)
except TypeError as exc:
    if str(exc) == "context must be a JSON object.":
        payload["context"] = {}
        state = await offload(thread_id, payload)
    else:
        raise

Prevention

When it happens

Trigger: Calling offload() with payload={'operation_id': 'x'} (context omitted -> None), {'context': []}, {'context': 'model_context_limit=1'}, or any non-dict object.

Common situations: Mistakenly passing a list of context entries, serializing context to a JSON string before embedding it, an optional-context caller passing None where the API requires at least an empty object, or a key-name typo putting settings at the wrong level.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/51c53f5d4c3ca08e. Report an issue: GitHub.