stride3d/stride · error · InvalidOperationException

Media is already open.

Error message

Media is already open.

What it means

FFmpegMedia.Open throws this InvalidOperationException when Open is called on a media instance that is already open (IsOpen is true). An FFmpegMedia wraps one AVFormatContext, so it cannot open a second URL/stream without being closed first. The message is logged via the TODO-logged path and thrown to the caller.

Solutions

  1. Call Close (or Dispose) on the FFmpegMedia before opening it again.
  2. Check the IsOpen property before calling Open and skip or recreate the instance.
  3. Create a new FFmpegMedia instance for each asset/source instead of reusing one.

Example fix

// before
if (media.IsOpen)
    media.Open(url); // throws
// after
if (media.IsOpen)
    media.Close();
media.Open(url);
Defensive patterns

Strategy: validation

Validate before calling

if (media.IsOpen) media.Close(); // or skip the Open call

Type guard

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

Try / catch

try
{
    media.Open(url);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("already open"))
{
    // reuse existing open media or close and retry
}

Prevention

When it happens

Trigger: Calling Open (directly, or via CreateAssets / DoCommandOverride) twice on the same FFmpegMedia instance without calling Close/Dispose in between.

Common situations: Reusing a cached FFmpegMedia for a second playback; a load/asset-creation pipeline invoking CreateAssets on a media that was opened earlier; event handlers triggering Open again while the first open is still active.

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

Appendix: source

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

        }

        [CanBeNull]
        public StreamInfo GetStreamInfo(VideoStream stream) => currentStreams.TryGetValue(stream, out var streamInfo) ? streamInfo : null;

        /// <summary>
        /// Opens this media.
        /// </summary>
        /// <remarks>
        /// Once the media is open, the collection of <see cref="Streams"/> is populated.
        /// </remarks>
        public void Open(string url, long startPosition = 0, long length = -1)
        {
            FFmpegUtils.EnsurePlatformSupport();
            if (isDisposed)
                throw new ObjectDisposedException(nameof(FFmpegMedia));
            if (IsOpen)
                // TODO: log?
                throw new InvalidOperationException(@"Media is already open.");

            if (startPosition != 0 && length != -1)
                url = $@"subfile,,start,{startPosition},end,{startPosition + length},,:{url}";

            var pFormatContext = ffmpeg.avformat_alloc_context();
            var ret = ffmpeg.avformat_open_input(&pFormatContext, url, null, null);
            if (ret < 0)
            {
                Logger.Error($"Could not open file. Error code={ret.ToString("X8")}");
                Logger.Error(GetErrorMessage(ret));
                throw new ApplicationException(@"Could not open file.");
            }

            ret = ffmpeg.avformat_find_stream_info(pFormatContext, null);
            if (ret < 0)
            {
                Logger.Error($"Could not find stream info. Error code={ret.ToString("X8")}");
                Logger.Error(GetErrorMessage(ret));

View on GitHub (pinned to 96fad776d2)