langchain-ai/deepagents · error · ValueError

PendingNotification {self.key!r} must declare at least one a

Error message

PendingNotification {self.key!r} must declare at least one action

What it means

`PendingNotification` must declare at least one action, because a notification with no buttons/commands can never be resolved by the registry. `__post_init__` raises a `ValueError` naming the notification's key when `actions` is empty.

Source

Thrown at libs/code/deepagents_code/notifications.py:125

    actions: tuple[NotificationAction, ...]
    """Available actions, rendered as rows in the modal."""

    payload: Payload
    """Kind-specific typed data consumed by the action dispatcher."""

    def __post_init__(self) -> None:
        """Enforce basic invariants at construction time.

        Raises:
            ValueError: If `key` is empty, `actions` is empty, or more
                than one action is marked `primary=True`.
        """
        if not self.key:
            msg = "PendingNotification.key must be non-empty"
            raise ValueError(msg)
        if not self.actions:
            msg = f"PendingNotification {self.key!r} must declare at least one action"
            raise ValueError(msg)
        primaries = sum(1 for a in self.actions if a.primary)
        if primaries > 1:
            msg = (
                f"PendingNotification {self.key!r} has {primaries} primary actions; "
                "at most one is allowed"
            )
            raise ValueError(msg)


class NotificationRegistry:
    """In-memory store of pending notifications.

    Instance-scoped (one per app) so test apps don't pollute each other.
    Owns the bidirectional key-to-toast-identity binding so callers
    cannot accidentally desynchronize the click-routing indices.
    """

    def __init__(self) -> None:

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Always pass at least one `NotificationAction` (make it primary if it's the sole one)
  2. Filter actions first and skip creating the notification if none survive
  3. Provide a default action such as a 'Dismiss' or 'Open' action

Example fix

// before
note = PendingNotification(key="deploy", actions=[a for a in acts if a.enabled])
// after
enabled = [a for a in acts if a.enabled]
if not enabled:
    return
note = PendingNotification(key="deploy", actions=enabled)
Defensive patterns

Strategy: validation

Validate before calling

if not actions:
    raise ValueError("PendingNotification requires at least one action")

Type guard

def has_actions(d: dict[str, object]) -> TypeGuard[dict[str, object]]:
    acts = d.get("actions")
    return isinstance(acts, list) and len(acts) > 0

Try / catch

try:
    note = PendingNotification(key=key, actions=actions)
except ValueError as e:
    logging.warning("dropping notification %r: %s", key, e)

Prevention

When it happens

Trigger: Constructing `PendingNotification(key="x", actions=[])` or `actions=None`, typically when actions are collected dynamically (e.g. filtered from a list that came back empty).

Common situations: Filtering actions by permissions and getting an empty list; deserializing a notification from JSON without the actions field; building a purely informational notification that the API doesn't support.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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