stride3d/stride · error · Exception

Unable to read

Error message

Unable to read: {0} 

What it means

MediaCodecExtractorBase.Initialize opens the media file on Android via Java.IO.File. If the file exists but is not readable (or does not exist), it throws a generic Exception 'Unable to read: <path>' before any extractor is created.

Solutions

  1. Check File.Exists and CanRead on the path before calling Initialize and surface a clear error.
  2. Copy bundled/streamed assets to the app's writable internal storage (FilesDir/CacheDir) and pass that path.
  3. Request and grant Android storage runtime permissions (or use app-scoped storage / SAF).
  4. Verify the path string (case, extension, absolute vs relative) matches the on-device file.

Example fix

// before
extractor.Initialize("/sdcard/DCIM/movie.mp4", MediaType.Video);
// after
var path = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "movie.mp4");
CopyAssetTo("movie.mp4", path); // copy from assets to app storage
if (System.IO.File.Exists(path))
    extractor.Initialize(path, MediaType.Video);
Defensive patterns

Strategy: validation

Validate before calling

var f = new Java.IO.File(url);
if (!f.Exists() || !f.CanRead())
    throw new IOException($"Media file missing or unreadable: {url}");
extractor.Initialize(url, mediaType);

Try / catch

try { extractor.Initialize(url, mediaType); }
catch (Exception ex) when (ex.Message.StartsWith("Unable to read:")) { /* fall back to app-storage copy of the asset */ }

Prevention

When it happens

Trigger: Passing a URL/path to a file with no read permission, a non-existent path, an Android storage location not accessible to the app (e.g. external storage without permission), or a content:// URI that cannot be mapped to a File.

Common situations: Missing READ_EXTERNAL_STORAGE / storage runtime permission; streaming assets not copied to a readable location; path case-sensitivity mismatches on Android; files in app-private dirs of another app.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Video/Android/MediaCodecExtractorBase.cs:106

        protected MediaCodecExtractorBase(VideoInstance videoInstance, MediaSynchronizer scheduler, Surface decoderOutputSurface = null)
        {
            Scheduler = scheduler;
            VideoInstance = videoInstance;
            this.decoderOutputSurface = decoderOutputSurface;

            currentState = SchedulerAsyncCommandEnum.Stop;
        }

        public void Initialize(IServiceRegistry services, string url, long startPosition, long length)
        {
            if (isInitialized)
                return;

            try
            {
                inputFile = new Java.IO.File(url);
                if (!inputFile.CanRead())
                    throw new Exception(string.Format("Unable to read: {0} ", inputFile.AbsolutePath));

                inputFileDescriptor = new Java.IO.FileInputStream(inputFile);

                // ===================================================================================================
                // Initialize the audio media extractor
                mediaExtractor = new MediaExtractor();
                mediaExtractor.SetDataSource(inputFileDescriptor.FD, startPosition, length);

                var videoTrackIndex = FindTrack(mediaExtractor, MediaType.Video);
                var audioTrackIndex = FindTrack(mediaExtractor, MediaType.Audio);
                HasAudioTrack = audioTrackIndex >= 0;

                mediaTrackIndex = MediaType == MediaType.Audio ? audioTrackIndex : videoTrackIndex;
                if (mediaTrackIndex < 0)
                    throw new Exception(string.Format($"No {MediaType} track found in: {inputFile.AbsolutePath}"));

                mediaExtractor.SelectTrack(mediaTrackIndex);

View on GitHub (pinned to 96fad776d2)