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

Abierto
#1,274 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 2 días

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
3/5
Tiempo estimado
1-2 días
Aptitud para principiantes
64/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
dart, flutter

Línea de trabajo

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.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

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
Lenguaje dominante
Dart
Estrellas
421
Forks
260
Merge medio
2 d 8 h
PR fusionados (30 d)
25

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de livekit/client-sdk-flutter

Todos los issues de livekit/client-sdk-flutter

Issues similares

Más issues de Dart

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.