Skip to content

Event listener dies: KeyError 'id' in _get_ring_event — some Ring FCM payloads no longer contain ding.id #537

Description

@portsparky

Describe the bug

Since roughly 2026-07-19 (worsening through late July), some Ring FCM push notifications arrive with an event.ding object that has no id key. _get_ring_event() crashes on every such message, and after 3 sequential callback errors firebase_messaging shuts the push receiver down entirely — killing realtime events for all devices until the listener is restarted.

ERROR (MainThread) [firebase_messaging.fcmpushclient] Unexpected exception calling notification callback
Traceback (most recent call last):
  File ".../firebase_messaging/fcmpushclient.py", line 456, in _handle_data_message
    self.callback(ret_val, msg.persistent_id, self.callback_context)
  File ".../ring_doorbell/listen/eventlistener.py", line 297, in _on_notification
    ring_event = self._get_ring_event(msg_data)
  File ".../ring_doorbell/listen/eventlistener.py", line 323, in _get_ring_event
    event_id = int(event["ding"]["id"])
                   ~~~~~~~~~~~~~^^^^^^
KeyError: 'id'
ERROR (MainThread) [firebase_messaging.fcmpushclient] Shutting down push receiver due to 3 sequential errors of type ErrorType.NOTIFY

Environment

  • ring-doorbell 0.9.14 (via Home Assistant 2026.7.4, Python 3.14)
  • 13 Ring cameras (mix of battery + wired, indoor + outdoor)

Observations

  • Restarting the listener (reloading the HA integration) restores push, but it dies again within ~1–2 h once more id-less payloads arrive. 70+ occurrences of this exact traceback in the last few days of logs.
  • It appears device/notification-type dependent: two cameras stopped registering push events entirely around Jul 19 (their motions seemingly always produce the new payload), while other cameras continued working between crashes.
  • Current master still has the unguarded access at the same line, so this affects the latest code too.

Suggested fix

Treat a missing ding.id defensively in _get_ring_event (e.g. event["ding"].get("id"), falling back to a synthetic id or skipping with a debug log) so one unexpected payload variant cannot take down the whole receiver. I have debug logging enabled and will attach a sanitised capture of the offending payload when the next one lands.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions