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
- Call Close (or Dispose) on the FFmpegMedia before opening it again.
- Check the IsOpen property before calling Open and skip or recreate the instance.
- 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
- Check IsOpen before every Open call.
- Keep one FFmpegMedia per source; create new instances for new assets.
- Always Close/Dispose media in finally blocks.
- Avoid calling Open re-entrantly from event handlers.
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
- Seek failed: MediaCodecScheduler is null
- Could not find asset
- Expect name1=value1;name2=value2 format.
- assetItem must be an absolute path
- Cannot modify a YamlAssetMetadata after it has been…
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)