[bug] Full reconnect: a rePublishAllTracks() failure escapes the EngineRestartedEvent handler and RoomReconnectedEvent is never emitted

Aperta
#1,274 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 2 giorni

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
64/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
dart, flutter

Direzione di ricerca

Start in Room._setUpEngineListeners in livekit_client/src/core/room.dart and trace the EngineRestartedEvent handler through rePublishAllTracks() in livekit_client/src/participant/local.dart. Compare the expected failure handling with the cited handleRestarted behavior in client-sdk-js. Done means a republish failure does not prevent reconnect completion, and muted stopped tracks do not trigger the reported failure.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Describe the bug

In Room._setUpEngineListeners, the EngineRestartedEvent handler awaits rePublishAllTracks() without a try/catch:

..on<EngineRestartedEvent>((event) async {
  // re-publish all tracks
  await localParticipant?.rePublishAllTracks();
  for (var participant in _remoteParticipants.toList()) { /* sendUpdateTrackSettings() */ }
  events.emit(const RoomReconnectedEvent());
  notifyListeners();
})

If republishing throws, the error escapes the listener as an unhandled async error and the rest of the handler is skipped: remote track settings are not re-sent, RoomReconnectedEvent is never emitted and listeners are not notified. RoomConnectedEvent is still emitted from the join response, so apps that only wait for RoomReconnectedEvent stay in a "reconnecting" state.

We see two variants in production (Crashlytics). In both, the local microphone had been muted with setMicrophoneEnabled(false) (default stopAudioCaptureOnMute: true) before the full reconnect.

Android 16:

Unable to RTCPeerConnection::addTransceiver: addTransceiver(): track is null
#0 RTCPeerConnectionNative.addTransceiver (flutter_webrtc/src/native/rtc_peerconnection_impl.dart:650)
#1 EngineInternalMethods.createTransceiverRTCRtpSender (livekit_client/src/core/engine.dart:1682)
#2 LocalParticipant._publishAudioTrack.negotiate (livekit_client/src/participant/local.dart:203)
#4 LocalParticipant._publishAudioTrack (livekit_client/src/participant/local.dart:210)
#5 SerialRunner.run (livekit_client/src/support/serial_runner.dart:45)
#6 LocalParticipant.publishAudioTrack (livekit_client/src/participant/local.dart:160)
#7 LocalParticipant.rePublishAllTracks (livekit_client/src/participant/local.dart:650)
#8 Room._setUpEngineListeners.<anonymous closure> (livekit_client/src/core/room.dart:622)

iOS 27.0.1 (after audio session interruptions):

LiveKit Exception: [AudioSessionException] Failed to configure the audio session (audio engine error -4100)
#0 LocalAudioTrack.startCapture (livekit_client/src/track/local/audio.dart:104)
#1 Track.start (livekit_client/src/track/track.dart:113)
#2 LocalParticipant._publishAudioTrack (livekit_client/src/participant/local.dart:182)
#3 SerialRunner.run (livekit_client/src/support/serial_runner.dart:45)
#4 LocalParticipant.publishAudioTrack (livekit_client/src/participant/local.dart:160)
#5 LocalParticipant.rePublishAllTracks (livekit_client/src/participant/local.dart:650)
#6 Room._setUpEngineListeners.<anonymous closure> (livekit_client/src/core/room.dart:622)

To Reproduce

  1. Connect, enable the microphone, then disable it with setMicrophoneEnabled(false).
  2. Force a full reconnect: kill the server (kill -9 on a local livekit-server --dev) and start it again within a few seconds.
  3. On Android, rePublishAllTracks() throws "track is null", the exception is unhandled and RoomReconnectedEvent is not emitted.

Reproduced on an Android emulator (API 37) against livekit-server 1.13.11. With the microphone enabled during the reconnect there is no error.

Expected behavior

The same as handleRestarted in client-sdk-js (src/room/CoreRoom.ts), where a republish failure is logged and the reconnect still completes:

try {
  await this.localParticipant.republishAllTracks(undefined, true);
} catch (error) {
  this.log.error('error trying to re-publish tracks after reconnection', { error });
}
// ...
this.emit(RoomEvent.Reconnected);

Also, client-sdk-js does not restart muted tracks before republishing (!track.isMuted), while publishAudioTrack always calls track.start(). That call is what fails for the muted, stopped track in both variants above.

Platform information

  • Flutter version: 3.47.8 (stable)
  • Plugin version: livekit_client 2.13.2 (the same handler is on main as of 2026-11-02), flutter_webrtc 1.6.3
  • Flutter target OS: Android (emulator and real devices), iOS (real devices)
  • Flutter target OS version: Android 16 and API 37 emulator, iOS 27.0.1
  • Flutter console log: stack traces above
Lingua principale
Dart
Stelle
421
Fork
260
Merge medio
2g 8h
PR unite (30g)
25

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di livekit/client-sdk-flutter

Tutte le issue di livekit/client-sdk-flutter

Issue simili

Altre issue su Dart

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.