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

  1. Dispose (or reset) the backend before calling Initialize again
  2. Create a new AVFoundationVideoBackend instance for each video/URL
  3. In the caller, guard re-initialization: skip if already initialized with the same URL
  4. 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

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


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)