Describe the bug
When Room.disconnect() is called while incoming text streams are open, every open stream channel is closed with an exception cause (IncomingDataStreamManagerImpl.clearOpenStreams):
descriptor.channel.close(StreamException.TerminatedException())
Because TextStreamReceiver.flow is channel.receiveAsFlow(), that exception is rethrown into whatever coroutine is collecting the receiver's flow. In our app the collectors run in a session-scoped coroutine, so a clean, client-initiated disconnect tears down the scope as an uncaught exception:
Session scope canceled with error: UnknownError(cause=StreamException$TerminatedException)
If a stream's header has arrived but its trailer has not yet been received at disconnect time (typical for in-progress transcription segments), this fires on every normal hang-up.
Steps to reproduce
room.registerTextStreamHandler(topic) { receiver, _ -> scope.launch { receiver.flow.collect { ... } } }
- Have the remote participant publish to the topic continuously (e.g. live transcription).
- Call
room.disconnect() while a stream is open.
- The collector throws
StreamException.TerminatedException.
Expected behavior
One of:
- A clean client-initiated disconnect closes stream channels without a cause (the same way
handleStreamTrailer closes channels on normal completion), so collectors complete normally; or
- The current behavior is the intended contract, and it's documented. Neither the text streams guide nor the API reference for
TerminatedException ("Stream terminated before completion") currently says collectors will receive this on room disconnect.
Possibly related: #881 is the same pattern with StreamException$IncompleteException — stream-channel close causes escaping into consumer coroutines as fatal exceptions. A documented contract for stream error delivery would cover both.
Device Info:
- LiveKit SDK version: 2.25.3 (behavior unchanged on
main as of 2026-06-10)
- Observed on: Pixel device, Android 16
Describe the bug
When
Room.disconnect()is called while incoming text streams are open, every open stream channel is closed with an exception cause (IncomingDataStreamManagerImpl.clearOpenStreams):Because
TextStreamReceiver.flowischannel.receiveAsFlow(), that exception is rethrown into whatever coroutine is collecting the receiver's flow. In our app the collectors run in a session-scoped coroutine, so a clean, client-initiated disconnect tears down the scope as an uncaught exception:If a stream's header has arrived but its trailer has not yet been received at disconnect time (typical for in-progress transcription segments), this fires on every normal hang-up.
Steps to reproduce
room.registerTextStreamHandler(topic) { receiver, _ -> scope.launch { receiver.flow.collect { ... } } }room.disconnect()while a stream is open.StreamException.TerminatedException.Expected behavior
One of:
handleStreamTrailercloses channels on normal completion), so collectors complete normally; orTerminatedException("Stream terminated before completion") currently says collectors will receive this on room disconnect.Possibly related: #881 is the same pattern with
StreamException$IncompleteException— stream-channel close causes escaping into consumer coroutines as fatal exceptions. A documented contract for stream error delivery would cover both.Device Info:
mainas of 2026-06-10)