stride3d/stride · error · InvalidOperationException

Seek failed: MediaCodecScheduler is null

Error message

Seek failed: MediaCodecScheduler is null

What it means

Thrown by MediaCodecVideoBackend.Seek when the underlying media synchronizer has not been created (or has been released) when a seek is requested. The library treats a seek on an un-initialized/disposed backend as a programming error, so it throws immediately rather than silently ignoring the request. The message mentions 'MediaCodecScheduler' (the synchronizer/scheduler object) even though the guard checks mediaSynchronizer.

Solutions

  1. Ensure Initialize completed successfully before wiring UI seek handlers to the backend
  2. Guard Seek call sites: only call when the backend reports it is initialized/playing
  3. Check that teardown/Dispose nulls or blocks Seek, and unsubscribe UI events on dispose
  4. Catch InvalidOperationException around Seek and ignore/log if not yet initialized

Example fix

// before
videoBackend.Seek(newPosition); // may throw if not initialized
// after
if (videoBackend.IsInitialized)
    videoBackend.Seek(newPosition);
else
    Logger.Warning("Seek ignored: backend not initialized");
Defensive patterns

Strategy: try-catch

Validate before calling

if (videoBackend == null || !videoBackend.IsInitialized)
    return; // don't attempt to seek yet

Type guard

static bool CanSeek(MediaCodecVideoBackend b) => b is { } && b.IsInitialized && !b.IsDisposed;

Try / catch

try
{
    videoBackend.Seek(position);
}
catch (InvalidOperationException)
{
    Logger.Warning("Seek before backend ready; ignoring");
}

Prevention

When it happens

Trigger: Calling Seek(TimeSpan) before the backend finished initialization (mediaSynchronizer still null), or after the backend was torn down and mediaSynchronizer.Stop()/release paths nulled it. Any code path that reaches Seek without a successful Initialize is affected.

Common situations: UI seek-bar handlers firing before video playback is ready; calling Seek on a video component whose Load failed earlier; seeking after Dispose due to a race between teardown and user input; platform where Initialize aborted early but the control is still interactive.

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/e76e718bd9143c69. Report an issue: GitHub.

Appendix: source

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

        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)
            throw new InvalidOperationException("Seek failed: MediaCodecScheduler is null");
        mediaSynchronizer.Seek(time);
    }

    public override void SetPlaybackSpeed(float speed) => mediaSynchronizer.SpeedFactor = speed;

    public override void SetAudioVolume(float volume)
    {
        if (audioSoundInstance != null)
            audioSoundInstance.Volume = volume;
        foreach (var controller in audioControllers)
            controller.Volume = volume;
    }

    public override void UpdatePlayRange() => mediaSynchronizer.PlayRange = Instance.PlayRange;

    public override void UpdateLoopRange()
    {
        mediaSynchronizer.IsLooping = Instance.IsLooping;

View on GitHub (pinned to 96fad776d2)