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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions