stride3d/stride · error · InvalidOperationException

AVAssetReader.StartReading failed

Error message

AVAssetReader.StartReading failed: {(err != null ? err.LocalizedDescription : "unknown")}

What it means

The AVAssetReader was created successfully but StartReading() returned false, meaning the reader could not begin producing samples; reader.Error supplies the underlying NSError. This happens after output configuration, so the failure is in starting the read pipeline.

Solutions

  1. Read the appended err.LocalizedDescription for the concrete cause
  2. Validate startTime is within the asset duration before CreateReader
  3. Simplify outputSettings (use kCVPixelFormatType32BGRA or device-preferred formats)
  4. Verify the asset is playable: check asset.Playable / tracks non-empty
  5. Test on a physical device vs simulator — some decoders behave differently
Defensive patterns

Strategy: try-catch

Validate before calling

if (startTime > asset.Duration) startTime = asset.Duration;
// and confirm asset has a video track:
var tracks = asset.TracksWithMediaType(AVMediaType.Video, out _);
if (tracks.Length == 0) throw new InvalidOperationException("no video track");

Try / catch

try { backend.Initialize(url, start, len); }
catch (InvalidOperationException ex) when (ex.Message.Contains("StartReading failed"))
{ /* retry with default output settings or clamp startTime */ }

Prevention

When it happens

Trigger: StartReading fails due to an invalid output settings combination (e.g. pixel format unsupported on device), asset becoming invalid after creation, time range settings conflicting with the asset, or resource exhaustion.

Common situations: Requesting a pixel format not supported on the target iOS device/simulator; seeking to a startTime beyond the asset duration producing an invalid time range; playing DRM-protected or corrupted assets; memory pressure on device.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/a43465293424dbb7. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Video/Backends/AVFoundationVideoBackend.cs:289

        // Ask the reader to deliver decoded BGRA pixel buffers backed by IOSurface. BGRA is the
        // VideoToolbox native output format for H.264/HEVC SDR content — picking it avoids an
        // internal NV12→RGB conversion. The IOSurface is imported as a VkImage in UploadFrameToTarget.
        var settings = new NSMutableDictionary
        {
            [CVPixelBuffer.PixelFormatTypeKey] = NSNumber.FromInt32((int)CVPixelFormatType.CV32BGRA),
            [CVPixelBuffer.IOSurfacePropertiesKey] = new NSDictionary(),
        };
        videoOutput = new AVAssetReaderTrackOutput(videoTrack, settings)
        {
            // The default of true caches output buffers via the track output's internal pool which
            // is what we want — keeps each frame available until we Dispose() it.
            AlwaysCopiesSampleData = false,
        };
        reader.AddOutput(videoOutput);
        if (!reader.StartReading())
        {
            var err = reader.Error;
            throw new InvalidOperationException(
                $"AVAssetReader.StartReading failed: {(err != null ? err.LocalizedDescription : "unknown")}");
        }
    }

    private void DisposeReader()
    {
        videoOutput?.Dispose();
        videoOutput = null;
        reader?.Dispose();
        reader = null;
    }

    private void UploadFrameToTarget(CVPixelBuffer pixelBuffer)
    {
        var target = Instance.VideoComponent.Target;
        if (target == null)
            return;

View on GitHub (pinned to 96fad776d2)