langchain-ai/deepagents · error · ValueError

PendingNotification {self.key!r} has {primaries} primary act

Error message

PendingNotification {self.key!r} has {primaries} primary actions; at most one is allowed

What it means

At most one action in a `PendingNotification` may be marked `primary=True`; `__post_init__` counts primaries and raises a `ValueError` naming the key and the count when more than one is found. This enforces a single highlighted action in the UI.

Source

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

        """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:
        """Initialize an empty registry."""
        self._entries: dict[str, PendingNotification] = {}
        self._key_to_toast: dict[str, str] = {}
        self._toast_to_key: dict[str, str] = {}

    def add(self, notification: PendingNotification) -> None:
        """Register a new notification or replace an existing one with the same key.

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Set `primary=True` on exactly one action, demoting the rest to `primary=False`
  2. When merging lists, keep the first primary and clear the flag on the others
  3. Add a normalization step before construction: `for i, a in enumerate(actions): a.primary = a.primary and i == first_primary_index`

Example fix

// before
note = PendingNotification(key="deploy", actions=[Approve(primary=True), Reject(primary=True)])
// after
note = PendingNotification(key="deploy", actions=[Approve(primary=True), Reject(primary=False)])
Defensive patterns

Strategy: validation

Validate before calling

primaries = sum(1 for a in actions if a.primary)
if primaries > 1:
    raise ValueError(f"at most one primary action allowed, got {primaries}")

Try / catch

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

Prevention

When it happens

Trigger: Constructing a notification whose actions list contains two or more actions with `primary=True`, often after merging action lists or copying actions from another notification.

Common situations: Appending a default primary action to a list that already contains one; combining actions from multiple sources without deduplicating the primary flag; a config file that marks several buttons as primary.

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/6ce497f516abfacc. Report an issue: GitHub.