stride3d/stride · error · Exception

Failed to create Celt decoder.

Error message

Failed to create Celt decoder.

What it means

Thrown from the Celt constructor when opus_custom_decoder_create returns NULL after the custom mode was created successfully. The native codec could not allocate or configure a decoder for the given channel count. Encoding-only or decoding-only paths may still be affected at construction time because the decoder is always created.

Solutions

  1. Verify the channel count is supported by the Celt decoder (typically 1 or 2).
  2. Ensure the correct native celt/opus library is bundled and loadable for the target platform.
  3. Free memory or reduce concurrent codec instances if native allocation is failing under pressure.
  4. Update Stride / native dependencies to a matching version.

Example fix

// before
var celt = new Celt(48000, 256, inputChannels /* e.g. 6 */, true);
// after
var channels = Math.Min(inputChannels, 2);
var celt = new Celt(48000, 256, channels, true); // downmix before encoding
Defensive patterns

Strategy: try-catch

Validate before calling

public static bool IsSupportedChannelCount(int channels) => channels is 1 or 2;

Try / catch

try
{
    var celt = new Celt(48000, bufferSize, channels, decoderOnly);
}
catch (Exception ex) when (ex.Message.Contains("Failed to create Celt decoder"))
{
    logger.Error("Celt decoder creation failed; check channels and native lib.");
    celt = null;
}

Prevention

When it happens

Trigger: Constructing Celt with an unsupported channel count or when native decoder allocation fails (memory, bad native library build) on the AVFoundation/iOS path.

Common situations: Passing more channels than the codec supports; shipping a mismatched or stripped native opus/celt binary; low-memory conditions on mobile devices.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/d659374b941db5c6. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Audio/Native/Celt.AVFoundation.cs:51

        public int Channels { get; set; }

        private IntPtr mode;
        private IntPtr decoder;
        private IntPtr encoder;

        public Celt(int sampleRate, int bufferSize, int channels, bool decoderOnly)
        {
            SampleRate = sampleRate;
            BufferSize = bufferSize;
            Channels = channels;

            mode = opus_custom_mode_create(sampleRate, bufferSize, IntPtr.Zero);
            if (mode == IntPtr.Zero)
                throw new Exception("Failed to create Celt custom mode.");

            decoder = opus_custom_decoder_create(mode, channels, IntPtr.Zero);
            if (decoder == IntPtr.Zero)
                throw new Exception("Failed to create Celt decoder.");

            if (!decoderOnly)
            {
                encoder = opus_custom_encoder_create(mode, channels, IntPtr.Zero);
                if (encoder == IntPtr.Zero)
                    throw new Exception("Failed to create Celt encoder.");
            }
        }

        public void Dispose()
        {
            if (encoder != IntPtr.Zero) { opus_custom_encoder_destroy(encoder); encoder = IntPtr.Zero; }
            if (decoder != IntPtr.Zero) { opus_custom_decoder_destroy(decoder); decoder = IntPtr.Zero; }
            if (mode != IntPtr.Zero) { opus_custom_mode_destroy(mode); mode = IntPtr.Zero; }
        }

        public unsafe int Decode(byte[] inputBuffer, int inputBufferSize, short[] outputSamples)
        {

View on GitHub (pinned to 96fad776d2)