Skip to content

RingEventListener can remain started after FCM push receiver shuts down, leaving notifications dead until restart #526

Description

@rndm2

Problem

I am using the Home Assistant Ring integration, which uses python-ring-doorbell.

I am seeing a failure mode where the Ring command/API path can still work, but realtime feedback stops arriving. In Home Assistant this means Ring Intercom feedback entities stop updating:

  • doorbell event does not fire
  • button/intercom event does not fire
  • timestamp/last activity feedback stops updating
  • automations depending on Ring events stop working

A manual reload of the Ring integration restores the feedback path.

The logs show the Firebase/FCM push receiver failing and shutting down:

firebase_messaging.fcmpushclient: Unexpected exception during read
TimeoutError: SSL shutdown timed out
firebase_messaging.fcmpushclient: Shutting down push receiver due to 3 sequential errors of type ErrorType.CONNECTION

After that, the Ring listener path appears dead until the integration is reloaded.

Why I think this is a listener health/recovery issue

From reading the current RingEventListener implementation, started is set when the receiver starts, and stop() sets started = False. However, if the underlying FcmPushClient shuts itself down after repeated connection errors, it does not appear that RingEventListener.started is reliably updated or that the listener is automatically restarted.

That can leave a state like:

RingEventListener.started == True
but the underlying FCM receiver is no longer delivering notifications

For Home Assistant this is especially problematic because the Ring integration can treat the listener as available while notification delivery is dead.

Expected behavior

If the underlying FCM push receiver stops because of connection errors, RingEventListener should either:

  1. mark itself as not started/unhealthy, or
  2. automatically reconnect/restart the receiver with backoff, or
  3. expose enough health state for the caller to detect the dead receiver and restart the listener.

Proposed API/implementation direction

It would be useful if RingEventListener exposed a health state, for example:

event_listener.healthy
event_listener.receiver_running
event_listener.receiver_error
event_listener.last_receiver_error
event_listener.last_notification_at

Or a method:

await event_listener.restart()

At minimum, when the FcmPushClient shuts down after repeated connection errors, the parent RingEventListener should not continue to look healthy.

Possible health checks:

started is True
subscribed is True
fcm_token is present
receiver object exists
receiver task/listen loop is still running
session_refresh_task exists and is not done
notification callback registry is present

If those are not true, callers such as Home Assistant should be able to detect that the listener is degraded.

Additional note

While reading the listener code, I also noticed a suspicious legacy GCM branch:

elif action.lower == PUSH_ACTION_DING.lower():

It looks like this may be intended to be:

elif action.lower() == PUSH_ACTION_DING.lower():

I do not know whether that branch is relevant to current FCM notifications, but it looks like a bug in the legacy notification parsing path.

Environment

  • Home Assistant Ring integration
  • ring-doorbell==0.9.14 as currently pinned by Home Assistant
  • Ring Intercom device
  • Failure appears after FCM/push receiver connection errors
  • Manual Home Assistant Ring integration reload restores notification delivery

Why this matters

Without a health/recovery signal, downstream integrations cannot distinguish:

no one rang the bell

from:

the push receiver has died and no events will ever arrive

This makes Ring event-based automations unreliable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions