stride3d/stride · error · Exception
Unable to read
Error message
Unable to read: {0} What it means
MediaCodec (Android) backend of StreamedBufferSoundSource throws this in InitializeMediaExtractor when the given mediaDataUrl points to a Java.IO.File that reports CanRead() == false. The library refuses to open a media source it cannot read at the filesystem level. It guards the MediaExtractor.SetDataSource call with an early, descriptive check.
Solutions
- Verify the file exists and is readable: new Java.IO.File(path).Exists() && CanRead() before calling
- Request runtime READ_EXTERNAL_STORAGE / MANAGE_EXTERNAL_STORAGE permissions on Android, or use app-internal storage for media files
- For bundled assets, copy the asset to app cache/files first, or use a data source that supports content:// streams
- Check the path for typos and confirm InputFile.AbsolutePath points to the actual media file, not a directory
Example fix
// before
var source = new StreamedBufferSoundSource("/storage/emulated/0/Music/track.ogg", services);
// after
var file = new Java.IO.File(path);
if (!file.Exists() || !file.CanRead())
throw new FileNotFoundException($"Media file not readable: {path}");
var source = new StreamedBufferSoundSource(path, services); Defensive patterns
Strategy: validation
Validate before calling
var f = new Java.IO.File(path);
if (f == null || !f.Exists() || f.IsDirectory || !f.CanRead())
throw new FileNotFoundException($"Media file not readable: {path}"); Try / catch
try
{
source = new StreamedBufferSoundSource(path, services);
}
catch (Exception ex) when (ex.Message.StartsWith("Unable to read:"))
{
Logger.Error($"Cannot read media at {path}: {ex.Message}");
source = null;
} Prevention
- Always check File.Exists() and CanRead() before creating streamed sources
- Request storage permissions at runtime on Android 6+
- Copy APK-bundled assets to internal storage before opening them as files
- Avoid hard-coded absolute paths to shared storage; prefer app-internal paths
When it happens
Trigger: Passing a path to InitializeMediaExtractor that does not exist, lacks read permission, is a directory, or lies in app-private storage inaccessible to the current context (e.g. raw absolute path to shared storage on modern Android without permissions).
Common situations: Hard-coded absolute paths like /storage/emulated/0/... on Android 10+ scoped storage; missing READ_EXTERNAL_STORAGE permission; typo in the media file path; asset bundled in the APK referenced as a file path instead of streamed via AssetFileDescriptor.
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
- unexpected result from audio decoder.DequeueOutputBuffer
- Unable to read
- The Media Codec has not been initialized for a media
- mediaCodec has already been initialized
- VideoInstance mediaCodec failed to get the AudioEngine
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/dd150ae8bf5e20d6.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Audio/StreamedBufferSoundSource.MediaCodec.cs:33
private MediaCodec audioMediaDecoder = null;
private int trackIndexAudio = -1;
private Java.IO.File InputFile;
private Java.IO.FileInputStream InputFileStream;
private bool extractionOutputDone = false;
private bool extractionInputDone = false;
partial void InitializeMediaExtractor(string mediaDataUrl, long startPosition, long length)
{
if (mediaDataUrl == null)
throw new ArgumentNullException(nameof(mediaDataUrl));
ReleaseMediaInternal();
InputFile = new Java.IO.File(mediaDataUrl);
if (!InputFile.CanRead())
throw new Exception(string.Format("Unable to read: {0} ", InputFile.AbsolutePath));
InputFileStream = new Java.IO.FileInputStream(InputFile.AbsolutePath);
audioMediaExtractor = new MediaExtractor();
audioMediaExtractor.SetDataSource(InputFileStream.FD, startPosition, length);
trackIndexAudio = FindAudioTrack(audioMediaExtractor);
if (trackIndexAudio < 0)
{
ReleaseMediaInternal();
Logger.Error($"The input file '{mediaDataUrl}' does not contain any audio track.");
return;
}
audioMediaExtractor.SelectTrack(trackIndexAudio);
var audioFormat = audioMediaExtractor.GetTrackFormat(trackIndexAudio);
var mime = audioFormat.GetString(MediaFormat.KeyMime);
audioMediaDecoder = MediaCodec.CreateDecoderByType(mime);View on GitHub (pinned to 96fad776d2)