stride3d/stride · error · InvalidOperationException

PlayMedia failed: MediaCodecScheduler is null

Error message

PlayMedia failed: MediaCodecScheduler is null

What it means

MediaCodecVideoBackend.Play was invoked but mediaSynchronizer (or mediaCodecVideoExtractor) is null, meaning Initialize never succeeded. The message says MediaCodecScheduler but the guard is on the synchronizer/extractor; playback cannot start without them.

Solutions

  1. Ensure Initialize succeeded before calling Play (check for swallowed exceptions)
  2. Handle/inspect exceptions from Initialize — a null mediaSynchronizer afterwards means it failed
  3. Do not call Play after Dispose; recreate and re-initialize the backend
  4. Order game logic so Play happens after the video finished loading/initializing

Example fix

// before
backend.Play(); // throws if Initialize failed or not called
// after
if (!backend.Initialize(url, 0, len)) throw new InvalidOperationException("video load failed");
backend.Play();
Defensive patterns

Strategy: validation

Validate before calling

bool ready = backend.IsInitialized; // synchronizer + extractor created
if (ready) backend.Play();

Type guard

bool CanPlay(MediaCodecVideoBackend b) => b.IsInitialized;

Try / catch

try { backend.Play(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("failed: MediaCodecScheduler is null"))
{ /* surface load failure; re-initialize backend */ }

Prevention

When it happens

Trigger: Calling Play before Initialize; Initialize threw earlier (e.g. failed audio setup at Initialize) leaving fields null; Play after Dispose; calling Play on a freshly constructed backend.

Common situations: Calling Play on a video entity whose backend failed to load the URL; lifecycle races where Play is invoked the same frame the component was added; forgetting that Initialize must precede Play.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Video/Backends/MediaCodecVideoBackend.cs:154

        lock (imageReaderLock)
        {
            imageReader?.Close();
            imageReader = null;
        }

        if (rgbaScratch != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(rgbaScratch);
            rgbaScratch = IntPtr.Zero;
            rgbaScratchSize = 0;
        }
    }

    public override void Play()
    {
        if (mediaSynchronizer == null || mediaCodecVideoExtractor == null)
            throw new InvalidOperationException("PlayMedia failed: MediaCodecScheduler is null");
        mediaSynchronizer.Play();
    }

    public override void Pause()
    {
        if (mediaSynchronizer == null)
            throw new InvalidOperationException("PauseMedia failed: MediaCodecScheduler is null");
        mediaSynchronizer.Pause();
    }

    public override void Stop()
    {
        mediaSynchronizer.Stop();
    }

    public override void Seek(TimeSpan time)
    {
        if (mediaSynchronizer == null)

View on GitHub (pinned to 96fad776d2)