stride3d/stride · error · InvalidOperationException

Media isn't open.

Error message

Media isn't open.

What it means

ExtractFrames extracts raw frames from an already-opened media. This InvalidOperationException is thrown when ExtractFrames is called on an FFmpegMedia whose Open() has not succeeded (IsOpen is false), or after the media was disposed.

Solutions

  1. Call Open(url) and confirm it succeeds before calling ExtractFrames
  2. Check the IsOpen property before extraction and open on demand
  3. Avoid using FFmpegMedia after Dispose; create a new instance
  4. Fix the root cause if Open previously failed (file path, codecs, memory)

Example fix

// before
media.ExtractFrames(stream, time => ...);
// after
if (!media.IsOpen) media.Open(url);
if (media.IsOpen)
    media.ExtractFrames(stream, time => ...);
Defensive patterns

Strategy: type-guard

Validate before calling

if (media.IsDisposed) throw new ObjectDisposedException(nameof(FFmpegMedia));
if (!media.IsOpen) media.Open(url);

Type guard

bool CanExtract(FFmpegMedia m) => !m.IsDisposed && m.IsOpen;

Try / catch

try { media.ExtractFrames(stream, cb); }
catch (InvalidOperationException ex) when (ex.Message == "Media isn't open.")
{
    media.Open(url);
    media.ExtractFrames(stream, cb);
}

Prevention

When it happens

Trigger: Calling ExtractFrames(stream,...) before calling Open(url), after Open threw (leaving the media not open), or after Dispose().

Common situations: Calling extraction APIs in the wrong order in editor/tools code; Open failed earlier due to a missing or corrupt file and the error was swallowed; using the media object after disposal.

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

Appendix: source

Thrown at sources/engine/Stride.Video/FFmpeg/FFmpegMedia.cs:204

            if (ret < 0)
            {
                Logger.Error($"Could not seek frame. Error code={ret.ToString("X8")}");
                Logger.Error(GetErrorMessage(ret));
                return false;
            }

            return true;
        }

        [ItemNotNull, NotNull]
        public int ExtractFrames([NotNull] FFmpegStream stream, int count)
        {
            FFmpegUtils.EnsurePlatformSupport();
            if (isDisposed)
                throw new ObjectDisposedException(nameof(FFmpegMedia));
            if (!IsOpen)
                // TODO: log?
                throw new InvalidOperationException(@"Media isn't open.");

            var pCodecpar = stream.AVStream->codecpar;
            var streamInfo = GetStreamInfo(stream);

            var dstData = new byte_ptrArray4();
            var dstLinesize = new int_array4();
            ffmpeg.av_image_fill_arrays(ref dstData, ref dstLinesize, (byte*)streamInfo.Image.Buffer, DestinationPixelFormat, pCodecpar->width, pCodecpar->height, 1);
            streamInfo.Image.Linesize = dstLinesize[0];

            var extractedFrameCount = 0;

            // FFmpeg 6.0+: av_init_packet removed; packets must be heap-allocated via av_packet_alloc.
            var pPacket = ffmpeg.av_packet_alloc();
            try
            {
                for (int i = 0; i < count; i++)
                {
                    var extractionStatus = ExtractNextImage(streamInfo, pPacket, stream.AVStream, dstData, dstLinesize);

View on GitHub (pinned to 96fad776d2)