Skip to content

KeyError in _on_room_event for track_subscribed when participant already removed by a racing disconnect #757

Description

@AKomplished-bug

Summary

Room._on_room_event raises KeyError in the track_subscribed handler when the remote participant has already been removed from self._remote_participants by a racing participant_disconnected (or a duplicate event). This is the same class of race that #743 fixed for track_unpublished, but the sibling handlers were left using an unguarded dict lookup.

Traceback (observed in production)

KeyError: 'sip-caller-+91XXXXXXXXXX'
  File ".../livekit/rtc/room.py", in _listen_task
    self._on_room_event(event.room_event)
  File ".../livekit/rtc/room.py", in _on_room_event
    rparticipant = self._remote_participants[event.track_subscribed.participant_identity]

It is caught by the except Exception: logging.exception(...) in _listen_task, so it does not crash the session, but it is logged as an error and reported to Sentry as noise. It shows up most often with SIP participants, whose connect/disconnect ordering is racier than typical WebRTC clients (a fast caller hangup interleaves participant_disconnected with an in-flight track_subscribed).

Root cause

On main (livekit-rtc 1.1.13), track_unpublished was made defensive in #743 with an explicit comment:

# The participant or publication may already have been removed by a
# racing disconnect or a duplicate event, so both lookups are done
# defensively ... instead of raising a KeyError that _listen_task logs as an error.
rp = self._remote_participants.get(identity)
if rp is not None:
    ...

but the following handlers in the same method still use a raw self._remote_participants[identity] and hit the identical race:

  • track_published
  • track_subscribed ← the one in the traceback above
  • track_unsubscribed
  • track_subscription_failed

Expected behavior

These handlers should look the participant (and publication) up defensively and skip the emit when the entry is already gone, mirroring track_unpublished / local_track_unpublished, rather than raising a KeyError.

Environment

  • livekit-rtc: 1.1.8 (observed); confirmed still present on main (1.1.13)
  • Python 3.11

Happy to send a PR mirroring the #743 approach.

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