Summary
Decentraland Explorer crashes with a fatal WebRTC assertion when a multi-channel audio interface is selected as the input device. The crash is instant and unrecoverable — the process aborts.
Environment
- OS: macOS (Darwin 25.2.0)
- Audio Device: Focusrite Scarlett 18i20, connected via docking station
- Explorer: Unity-based Decentraland Explorer (latest)
Error
Fatal error in: ../api/audio/audio_frame.cc, line 75
last system error: 0
Check failed: num_channels <= kMaxConcurrentChannels (20 vs. 8)
Full stack trace includes GPUI Pro NullReferenceException during the crash unwind, but the root cause is the WebRTC audio frame assertion.
Steps to Reproduce
- Connect a multi-channel audio interface (e.g. Focusrite Scarlett 18i20) to the system
- Select it as the input device in Decentraland's audio settings
- The client crashes immediately
If the multi-channel interface was previously selected, the client will remember this preference and automatically select it again on next launch. In this case, the crash occurs as soon as a scene loads — before the user has a chance to change the audio setting.
Confirmed Behavior
- The crash only occurs when the multi-channel device is actively selected as the input device
- Simply having the interface connected does not cause the crash
- Switching to MacBook internal mic in Decentraland settings, then restarting the client, resolves the crash — even with the Scarlett plugged in and turned on
- Switching back to the Scarlett as input while logged in immediately crashes the client again
Root Cause
The Rust audio capture layer (RustAudio/rust-audio/src/lib.rs in decentraland/client-sdk-unity) uses cpal to open the selected input device and selects the first F32-compatible config via with_max_sample_rate().config(). This takes whatever channel count the device reports with no clamping.
This channel count flows through unchanged:
rust_audio_input_stream_new_internal() → returns config.channels as u32
MicrophoneInfo.channels (C#)
MicrophoneRtcAudioSource → sets NumChannels = deviceMicrophoneAudioSource.MicrophoneInfo.channels
- LiveKit FFI → WebRTC
AudioFrame
RTC_CHECK_LE(num_channels, kMaxConcurrentChannels) — fatal assertion fails because the channel count exceeds 8
Voice chat only needs mono or stereo — there is no reason to pass the device's full channel count into the WebRTC pipeline.
Proposed Fix
Clamp the channel count to stereo at the audio capture level (see decentraland/client-sdk-unity#67):
Rust side (lib.rs) — prevents cpal from capturing unnecessary channels:
let mut config = supported_config.with_max_sample_rate().config();
config.channels = config.channels.min(2);
C# side (MicrophoneRtcAudioSource.cs) — defensive clamp before passing to LiveKit:
NumChannels = Math.Min(deviceMicrophoneAudioSource.MicrophoneInfo.channels, 2);
Affected Devices
Any multi-channel audio interface with >8 channels would trigger this crash when selected as input. Common examples:
- Focusrite Scarlett 18i20
- Universal Audio Apollo x8/x16
- MOTU 828/1248 series
- RME Fireface/Babyface series
- Any aggregate audio device combining multiple inputs
Workaround
If the client is crashing on launch due to a saved device preference:
- Turn off or unplug the multi-channel audio interface
- Launch the client — it will fall back to a different input device since the saved one is unavailable
- Go into Decentraland's audio settings and switch to a different input device (e.g. MacBook internal mic)
- The interface can now be turned back on or reconnected safely, as long as it is not re-selected as the input device
Summary
Decentraland Explorer crashes with a fatal WebRTC assertion when a multi-channel audio interface is selected as the input device. The crash is instant and unrecoverable — the process aborts.
Environment
Error
Full stack trace includes GPUI Pro NullReferenceException during the crash unwind, but the root cause is the WebRTC audio frame assertion.
Steps to Reproduce
If the multi-channel interface was previously selected, the client will remember this preference and automatically select it again on next launch. In this case, the crash occurs as soon as a scene loads — before the user has a chance to change the audio setting.
Confirmed Behavior
Root Cause
The Rust audio capture layer (
RustAudio/rust-audio/src/lib.rsindecentraland/client-sdk-unity) usescpalto open the selected input device and selects the first F32-compatible config viawith_max_sample_rate().config(). This takes whatever channel count the device reports with no clamping.This channel count flows through unchanged:
rust_audio_input_stream_new_internal()→ returnsconfig.channels as u32MicrophoneInfo.channels(C#)MicrophoneRtcAudioSource→ setsNumChannels = deviceMicrophoneAudioSource.MicrophoneInfo.channelsAudioFrameRTC_CHECK_LE(num_channels, kMaxConcurrentChannels)— fatal assertion fails because the channel count exceeds 8Voice chat only needs mono or stereo — there is no reason to pass the device's full channel count into the WebRTC pipeline.
Proposed Fix
Clamp the channel count to stereo at the audio capture level (see decentraland/client-sdk-unity#67):
Rust side (
lib.rs) — preventscpalfrom capturing unnecessary channels:C# side (
MicrophoneRtcAudioSource.cs) — defensive clamp before passing to LiveKit:Affected Devices
Any multi-channel audio interface with >8 channels would trigger this crash when selected as input. Common examples:
Workaround
If the client is crashing on launch due to a saved device preference: