{"record":{"id":"8b8aad05f95d000a","repo":"stride3d/stride","slug":"unable-to-read-0-mediacodecextractorbase","errorCode":null,"errorMessage":"Unable to read: {0} ","messagePattern":"Unable to read: (.+?) ","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Video/Android/MediaCodecExtractorBase.cs","lineNumber":106,"sourceCode":"        protected MediaCodecExtractorBase(VideoInstance videoInstance, MediaSynchronizer scheduler, Surface decoderOutputSurface = null)\n        {\n            Scheduler = scheduler;\n            VideoInstance = videoInstance;\n            this.decoderOutputSurface = decoderOutputSurface;\n\n            currentState = SchedulerAsyncCommandEnum.Stop;\n        }\n\n        public void Initialize(IServiceRegistry services, string url, long startPosition, long length)\n        {\n            if (isInitialized)\n                return;\n\n            try\n            {\n                inputFile = new Java.IO.File(url);\n                if (!inputFile.CanRead())\n                    throw new Exception(string.Format(\"Unable to read: {0} \", inputFile.AbsolutePath));\n\n                inputFileDescriptor = new Java.IO.FileInputStream(inputFile);\n\n                // ===================================================================================================\n                // Initialize the audio media extractor\n                mediaExtractor = new MediaExtractor();\n                mediaExtractor.SetDataSource(inputFileDescriptor.FD, startPosition, length);\n\n                var videoTrackIndex = FindTrack(mediaExtractor, MediaType.Video);\n                var audioTrackIndex = FindTrack(mediaExtractor, MediaType.Audio);\n                HasAudioTrack = audioTrackIndex >= 0;\n\n                mediaTrackIndex = MediaType == MediaType.Audio ? audioTrackIndex : videoTrackIndex;\n                if (mediaTrackIndex < 0)\n                    throw new Exception(string.Format($\"No {MediaType} track found in: {inputFile.AbsolutePath}\"));\n\n                mediaExtractor.SelectTrack(mediaTrackIndex);\n","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Video/Android/MediaCodecExtractorBase.cs#L88-L124","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check File.Exists and CanRead on the path before calling Initialize and surface a clear error.","Copy bundled/streamed assets to the app's writable internal storage (FilesDir/CacheDir) and pass that path.","Request and grant Android storage runtime permissions (or use app-scoped storage / SAF).","Verify the path string (case, extension, absolute vs relative) matches the on-device file."],"exampleFix":"// before\nextractor.Initialize(\"/sdcard/DCIM/movie.mp4\", MediaType.Video);\n// after\nvar path = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), \"movie.mp4\");\nCopyAssetTo(\"movie.mp4\", path); // copy from assets to app storage\nif (System.IO.File.Exists(path))\n    extractor.Initialize(path, MediaType.Video);","handlingStrategy":"validation","validationCode":"var f = new Java.IO.File(url);\nif (!f.Exists() || !f.CanRead())\n    throw new IOException($\"Media file missing or unreadable: {url}\");\nextractor.Initialize(url, mediaType);","typeGuard":null,"tryCatchPattern":"try { extractor.Initialize(url, mediaType); }\ncatch (Exception ex) when (ex.Message.StartsWith(\"Unable to read:\")) { /* fall back to app-storage copy of the asset */ }","preventionTips":["Copy bundled assets to internal storage before playback","Request Android storage permissions at runtime","Validate paths (exists + can-read) before Initialize","Use app-scoped storage rather than shared external storage"],"tags":["android","video","file-access","permissions"],"backgroundTag":"file-read-failed","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}