stride3d/stride · error · InvalidOperationException
AVFoundationVideoBackend already initialized.
Error message
AVFoundationVideoBackend already initialized.
What it means
AVFoundationVideoBackend.Initialize was called on a backend instance that is already initialized and holds a live AVAssetReader (reader != null). The backend does not support re-initialization while active; it must be disposed or reset first.
Solutions
- Dispose (or reset) the backend before calling Initialize again
- Create a new AVFoundationVideoBackend instance for each video/URL
- In the caller, guard re-initialization: skip if already initialized with the same URL
- Check the video component's lifecycle so each play cycle gets a fresh backend
Example fix
// before backend.Initialize(url, start, length); backend.Initialize(url, start, length); // throws // after if (backend.ReaderActive) backend.Dispose(); backend.Initialize(url, start, length);
Defensive patterns
Strategy: validation
Validate before calling
if (backend.IsInitialized) backend.Dispose(); backend.Initialize(url, startPosition, length);
Type guard
bool CanInitialize(AVFoundationVideoBackend b) => !b.IsInitialized;
Try / catch
try { backend.Initialize(url, start, len); }
catch (InvalidOperationException ex) when (ex.Message.Contains("already initialized"))
{ backend.Dispose(); backend.Initialize(url, start, len); } Prevention
- One backend instance per video session; recreate rather than re-init
- Track backend lifecycle state in the owning component
- Always Dispose on scene/component teardown
When it happens
Trigger: Calling Initialize twice on the same backend instance without Dispose/Reset in between; a video component re-assigning the same URL to an already-playing instance; lifecycle code that reuses backends across Play calls.
Common situations: Replaying the same video through a cached backend object; hot-reload or scene restart code re-initializing the shared backend; forgetting to call Dispose when switching videos.
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
- AVAssetReader create failed
- AVAssetReader.StartReading failed
- AVAssetReader (audio) create failed
- AVAssetReader.StartReading (audio) failed
- Game must be assigned before base.FinishedLaunching.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/ea41e3ac94aae553.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Video/Backends/AVFoundationVideoBackend.cs:58
private int videoWidth;
private int videoHeight;
private TimeSpan frameDuration;
private long adjustedTicksSinceLastFrame;
// Audio runs on the StreamedBufferSoundSource worker thread; video clock forwards to the synchronizer.
private MediaSynchronizer audioSynchronizer;
private StreamedBufferSound audioSound;
private SoundInstanceStreamedBuffer audioSoundInstance;
private readonly System.Collections.Generic.List<AudioEmitterSoundController> audioControllers = new();
public AVFoundationVideoBackend(VideoInstance instance) : base(instance) { }
public override bool UsesHardwareDecode => true; // AVAssetReader uses VideoToolbox
public override bool Initialize(string url, long startPosition, long length)
{
if (reader != null)
throw new InvalidOperationException("AVFoundationVideoBackend already initialized.");
try
{
tempFilePath = ExtractAssetSliceToTempFile(url, startPosition, length);
using var assetUrl = NSUrl.FromFilename(tempFilePath);
asset = AVAsset.FromUrl(assetUrl);
var videoTracks = asset.TracksWithMediaType(AVMediaTypes.Video.GetConstant());
if (videoTracks == null || videoTracks.Length == 0)
{
VideoInstance.Logger.Warning("AVFoundationVideoBackend: media has no video track.");
ReleaseMedia();
return false;
}
videoTrack = videoTracks[0];
var size = videoTrack.NaturalSize;View on GitHub (pinned to 96fad776d2)