{"record":{"id":"d01b5b13b033a268","repo":"langchain-ai/deepagents","slug":"pendingnotification-key-must-be-non-empty","errorCode":null,"errorMessage":"PendingNotification.key must be non-empty","messagePattern":"PendingNotification\\.key must be non-empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/notifications.py","lineNumber":122,"sourceCode":"    May contain install instructions, links, or version info.\n    \"\"\"\n\n    actions: tuple[NotificationAction, ...]\n    \"\"\"Available actions, rendered as rows in the modal.\"\"\"\n\n    payload: Payload\n    \"\"\"Kind-specific typed data consumed by the action dispatcher.\"\"\"\n\n    def __post_init__(self) -> None:\n        \"\"\"Enforce basic invariants at construction time.\n\n        Raises:\n            ValueError: If `key` is empty, `actions` is empty, or more\n                than one action is marked `primary=True`.\n        \"\"\"\n        if not self.key:\n            msg = \"PendingNotification.key must be non-empty\"\n            raise ValueError(msg)\n        if not self.actions:\n            msg = f\"PendingNotification {self.key!r} must declare at least one action\"\n            raise ValueError(msg)\n        primaries = sum(1 for a in self.actions if a.primary)\n        if primaries > 1:\n            msg = (\n                f\"PendingNotification {self.key!r} has {primaries} primary actions; \"\n                \"at most one is allowed\"\n            )\n            raise ValueError(msg)\n\n\nclass NotificationRegistry:\n    \"\"\"In-memory store of pending notifications.\n\n    Instance-scoped (one per app) so test apps don't pollute each other.\n    Owns the bidirectional key-to-toast-identity binding so callers\n    cannot accidentally desynchronize the click-routing indices.","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/notifications.py#L104-L140","documentation":"`PendingNotification` dataclass validation in `__post_init__` requires a non-empty `key`, since the key identifies the notification for deduplication and registry lookup. An empty (or missing) key raises a `ValueError` immediately at construction.","triggerScenarios":"Constructing `PendingNotification(key=\"\")` or `key=None`, often when the key is built from a variable that ended up empty (unresolved template, missing field in source data).","commonSituations":"Building notifications from upstream payloads where the id field is absent; string formatting that produced \"\"; forgetting to set a default key.","solutions":["Supply a stable, unique key at construction, e.g. derived from the event id","Skip constructing the notification when the source id is missing, logging instead","Guard with `if not event_id: return` before creating the PendingNotification"],"exampleFix":"// before\nnote = PendingNotification(key=event.get(\"id\", \"\"), ...)\n// after\nif not (event_id := event.get(\"id\")):\n    return\nnote = PendingNotification(key=event_id, ...)","handlingStrategy":"validation","validationCode":"if not key:\n    raise ValueError(\"Cannot create PendingNotification with an empty key\")","typeGuard":"def has_key(d: dict[str, object]) -> TypeGuard[dict[str, object]]:\n    return isinstance(d.get(\"id\"), str) and bool(d[\"id\"])","tryCatchPattern":"try:\n    note = PendingNotification(key=key, actions=actions)\nexcept ValueError as e:\n    logging.warning(\"dropping notification: %s\", e)","preventionTips":["Derive keys from stable upstream ids and verify them first","Skip rather than construct when the id is missing","Add a unit test for empty-key construction"],"tags":["python","validation","notifications","dataclass"],"backgroundTag":"schema-validation-failed","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}