langchain-ai/deepagents · error · ValueError
External event payload must be a non-empty string
Error message
External event payload must be a non-empty string
What it means
Alongside kind validation, `ExternalEvent.__post_init__` requires a non-empty, non-whitespace payload (`if not self.payload or not self.payload.strip()`). An empty payload carries no actionable information, so the dataclass rejects it at construction time rather than letting an inert event flow through the bus.
Source
Thrown at libs/code/deepagents_code/event_bus.py:78
payload: str
source: str
bypass: BypassTier = BypassTier.QUEUED
correlation_id: str | None = None
def __post_init__(self) -> None:
"""Validate invariants for direct construction.
Raises:
ValueError: If `kind` is not a known kind, the payload is empty
or whitespace-only, or the kind is `"signal"` but the payload
is not a recognized signal name.
"""
if self.kind not in _VALID_KINDS:
msg = f"Unknown external event kind: {self.kind!r}"
raise ValueError(msg)
if not self.payload or not self.payload.strip():
msg = "External event payload must be a non-empty string"
raise ValueError(msg)
if self.kind == "signal" and self.payload.strip().lower() not in _VALID_SIGNALS:
msg = (
f"Unknown external signal: {self.payload!r}; "
f"expected one of {sorted(_VALID_SIGNALS)}"
)
raise ValueError(msg)
class EventSource(Protocol):
"""Source of external events for the Textual app.
Implementations must be safe to `stop()` even when `start()` failed
partway through; the app always invokes `stop()` from a `finally` block.
"""
async def start(
self,
sink: Callable[[ExternalEvent], Awaitable[None]],View on GitHub (pinned to a1af029e6e)
Solutions
- Populate the payload with meaningful content on the producer side before emitting.
- Guard the producer: skip events whose payload is empty or whitespace-only.
- Strip and validate incoming socket messages before wrapping them in `ExternalEvent`.
Example fix
// before
ExternalEvent(kind="signal", payload=msg.strip().split(":")[1]) # may be empty
// after
parts = msg.strip().split(":", 1)
if len(parts) == 2 and parts[1].strip():
ExternalEvent(kind="signal", payload=parts[1]) Defensive patterns
Strategy: validation
Validate before calling
def safe_event(kind: str, payload: str):
if not payload or not payload.strip():
return None
return ExternalEvent(kind=kind, payload=payload) Type guard
def has_payload(payload: object) -> bool:
return isinstance(payload, str) and bool(payload.strip()) Try / catch
try:
event = ExternalEvent(kind=kind, payload=payload)
except ValueError as exc:
logger.warning("Dropping empty-payload event: %s", exc)
event = None Prevention
- Validate/strip incoming socket messages before constructing events.
- Skip empty frames at the producer rather than forwarding them.
- Check message-splitting logic for empty trailing segments.
When it happens
Trigger: Constructing `ExternalEvent(kind=<valid>, payload="")` or `payload=" "` — e.g. a socket producer forwarding a blank line, or splitting an incoming message without checking for empty segments.
Common situations: Unix-socket clients sending an empty JSON field; message framing that splits on newlines yielding empty trailing segments; templates/config generating empty payloads from unfilled variables.
Related errors
- Unknown external event kind: {self.kind!r}
- Unknown external signal: {self.payload!r}; expected one of {
- Provider name cannot be empty
- API key cannot be empty
- suffix must be empty or a short extension such as .md
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/409b14a849854220.
Report an issue: GitHub.