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
- Wrap the event in a JSON object envelope with `kind`, `payload`, and optional `bypass`/`correlation_id` fields.
- On the producer, serialize a dict, not a list or scalar.
- If emitting multiple events, write one JSON object per line (NDJSON), not an array.
- 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
- Serialize a dict on the producer; never a bare list or scalar.
- Emit one object per line, not an array of objects.
- Keep a shared envelope-builder helper for all producers.
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
- External event must be valid JSON: {exc.msg}
- External event kind must be one of {sorted(_VALID_KINDS)}; g
- Unknown external event kind: {self.kind!r}
- External event bypass must be a valid bypass tier: {exc}
- External event correlation_id must be a string when present
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/9b43ecfe2ed12cd8.
Report an issue: GitHub.