Skip to content

Unknown DataChannel error logged as console.error for graceful close events (audio-only rooms) #1953

Description

@ECREedukacja

Describe the bug

What I'm expecting

Joining and leaving an audio-only room (<LiveKitRoom video={false} audio={true} ...>) should not log console.error lines when no actual error has occurred.

What happens instead

On every room leave / route change, Unknown DataChannel error on lossy and/or Unknown DataChannel error on reliable is logged at error severity. The underlying browser event is a generic Event (not ErrorEvent) emitted during graceful close / ICE restart cleanup — event.message and event.error are undefined. There is no actual failure; audio works correctly. But the red console.error lines:

  • Get flagged by error-tracking tools (Sentry / Datadog RUM) as production errors
  • Confuse developers reviewing console output
  • Have no diagnostic value (payload { event } contains no usable information)

Code location

src/room/RTCEngine.ts:996-1006:

private handleDataError = (event: Event) => {
  const channel = event.currentTarget as RTCDataChannel;
  const channelKind = channel.maxRetransmits === 0 ? 'lossy' : 'reliable';

  if (event instanceof ErrorEvent && event.error) {
    const { error } = event.error;
    this.log.error(`DataChannel error on ${channelKind}: ${event.message}`, { error });
  } else {
    this.log.error(`Unknown DataChannel error on ${channelKind}`, { event });  // ← issue
  }
};

The else branch fires when event is NOT an ErrorEvent with event.error populated — i.e. there is no actual error data, yet it is logged at error severity.

Proposed fix

Downgrade else branch from log.error to log.debug (one-line diff):

   } else {
-    this.log.error(`Unknown DataChannel error on ${channelKind}`, { event });
+    this.log.debug(`Unknown DataChannel error on ${channelKind}`, { event });
   }

Rationale:

  • Real errors (with event.error populated) still take the if branch — unaffected
  • log.debug is invisible by default but available via setLogLevel('debug') for users actively debugging data channels
  • Zero behavioral change — only severity adjustment of an informational log

Reproduction

  1. Create a minimal audio-only room with livekit-client 2.19.0:
import { Room } from 'livekit-client';

const room = new Room();
await room.connect(serverUrl, token);
await room.localParticipant.setMicrophoneEnabled(true);
// ... use room for a bit ...
await room.disconnect();

Or, equivalently, using @livekit/components-react:

<LiveKitRoom token={token} serverUrl={url} video={false} audio={true} connect>
  <RoomAudioRenderer />
</LiveKitRoom>
  1. Trigger a leave (room.disconnect(), route change, or component unmount).
  2. Observe DevTools Console — red Unknown DataChannel error on lossy / Unknown DataChannel error on reliable lines appear.

Reproduces consistently across Chrome 130 / Firefox 132 / Safari 18 (tested) on every leave.

Logs

Unknown DataChannel error on lossy
  at HTMLDocument.<anonymous> (livekit-client.esm.mjs:21183)
  ...
Unknown DataChannel error on reliable
  at HTMLDocument.<anonymous> (livekit-client.esm.mjs:21183)
  ...

Payload object (when inspected): { event: Event { isTrusted: true, type: 'error', target: RTCDataChannel } } — no message, no error, no stack beyond the SDK's own log call site.

System Info

  System:
    OS: macOS 12.6.3
    CPU: (4) x64 Intel(R) Core(TM) i5-5250U CPU @ 1.60GHz
    Memory: 40.92 MB / 4.00 GB
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 24.15.0 - /usr/local/bin/node
    npm: 11.12.1 - /usr/local/bin/npm
  Browsers:
    Brave Browser: 110.1.48.171
    Safari: 17.6
  npmPackages:
    @livekit/components-react: ^2.9.21 => 2.9.21
    livekit-client: ^2.19.0 => 2.19.0
    livekit-server-sdk: ^2.15.3 => 2.15.3

Also reproduced on Chrome 130 and Firefox 132 (separate test machine).

Severity

annoyance

Additional Information

Workarounds attempted (none satisfactory)

  1. setLogExtension (Sentry-style log forwarding) — only forwards logs downstream, does not filter or suppress upstream console.error.
  2. setLogLevel('warn') on the engine logger — silences all errors, too broad.
  3. RoomOptions.logger / custom logger injection — not in stable public API.
  4. Avoid creating data channels when video: falseRTCEngine.createDataChannels() (line 827) is called unconditionally regardless of published media tracks.
  5. Override console.error globally — works but global side effect, fragile, breaks other error tooling.
  6. patch-package with the proposed one-line diff — current workaround in our project (Next.js 16 + React 19, audio-only tutoring app); applied at build time via postinstall.

Willing to submit PR

Yes — happy to open a PR with the one-line diff above if maintainers agree on the approach. Open to alternative approaches (e.g. add an option to silence specific log categories) if preferred.

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