langchain-ai/deepagents · error · TypeError

External event must be a JSON object

Error message

External event must be a JSON object

What it means

After JSON parsing succeeds, `decode_external_event` requires the decoded value to be a dict (JSON object) because the event envelope is accessed by field name. Any other JSON value — a string, number, array, boolean, or null — raises `TypeError`. This distinguishes shape errors (TypeError) from content errors (ValueError).

Source

Thrown at libs/code/deepagents_code/event_bus.py:381

        data: Raw JSON line.
        source: Transport-specific source label attached to the event.

    Returns:
        Parsed external event.

    Raises:
        TypeError: If the envelope is not a JSON object.
        ValueError: If any envelope field is missing, of the wrong type, or
            otherwise invalid.
    """
    try:
        raw = json.loads(data)
    except json.JSONDecodeError as exc:
        msg = f"External event must be valid JSON: {exc.msg}"
        raise ValueError(msg) from exc
    if not isinstance(raw, dict):
        msg = "External event must be a JSON object"
        raise TypeError(msg)

    kind = raw.get("kind")
    if kind not in _VALID_KINDS:
        msg = f"External event kind must be one of {sorted(_VALID_KINDS)}; got {kind!r}"
        raise ValueError(msg)

    payload = raw.get("payload")
    if not isinstance(payload, str) or not payload.strip():
        msg = "External event payload must be a non-empty string"
        raise ValueError(msg)

    bypass = raw.get("bypass", BypassTier.QUEUED.value)
    try:
        bypass_tier = BypassTier(bypass)
    except ValueError as exc:
        msg = f"External event bypass must be a valid bypass tier: {exc}"
        raise ValueError(msg) from exc

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Wrap the event in a JSON object envelope with `kind`, `payload`, and optional `bypass`/`correlation_id` fields.
  2. On the producer, serialize a dict, not a list or scalar.
  3. If emitting multiple events, write one JSON object per line (NDJSON), not an array.
  4. Catch `TypeError` in the reader to report envelope-shape problems distinctly.

Example fix

// before
echo '[{"kind":"noop","payload":"x"}]' | socat - UNIX-CONNECT:$SOCK

// after
echo '{"kind":"noop","payload":"x"}' | socat - UNIX-CONNECT:$SOCK
Defensive patterns

Strategy: type-guard

Validate before calling

import json

def assert_event_envelope(obj) -> None:
    if not isinstance(obj, dict):
        raise TypeError(f"event must be a dict, got {type(obj).__name__}")

Type guard

def is_event_envelope(value) -> bool:
    return isinstance(value, dict) and "kind" in value and "payload" in value

Try / catch

try:
    event = decode_external_event(data, source=source)
except TypeError:
    logger.warning("external event line is not a JSON object; envelope expected")
    return None

Prevention

When it happens

Trigger: Writing a bare JSON scalar or array to the external event socket, e.g. `"hello"`, `[1,2,3]`, `42`, or `null`, instead of an object like `{"kind":..., "payload":...}`.

Common situations: A producer sending a JSON array of events in one line instead of one object per line; sending just the payload string and forgetting the envelope; a misconfigured writer serializing a top-level list.

Related errors


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