AvaloniaUI/Avalonia · error · InvalidOperationException
Failed to open content stream
Error message
Failed to open content stream
What it means
Thrown by AndroidStorageFile.OpenRead when OpenContentStream returns null — i.e. neither the virtual-file path nor ContentResolver.OpenInputStream produced a usable Stream for the content:// URI. The file is bookmarked/referenced but Android cannot open it for reading at this moment.
Source
Thrown at src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs:484
public WellKnownAndroidStorageFolder(Activity activity, string identifier, AndroidUri uri, bool needsExternalFilesPermission)
: base(activity, uri, needsExternalFilesPermission)
{
Name = identifier;
}
public override string Name { get; }
}
internal sealed class AndroidStorageFile : AndroidStorageItem, IStorageBookmarkFile
{
public AndroidStorageFile(Activity activity, AndroidUri uri, AndroidStorageFolder? parent = null, AndroidUri? permissionRoot = null) : base(activity, uri, false, parent, permissionRoot)
{
}
public Task<Stream> OpenReadAsync() => Task.FromResult(OpenRead());
public Stream OpenRead() => OpenContentStream(Activity, Uri, false)
?? throw new InvalidOperationException("Failed to open content stream");
public Task<Stream> OpenWriteAsync() => Task.FromResult(OpenContentStream(Activity, Uri, true)
?? throw new InvalidOperationException("Failed to open content stream"));
private Stream? OpenContentStream(Context context, AndroidUri uri, bool isOutput)
{
var isVirtual = IsVirtualFile(context, uri);
if (isVirtual)
{
Logger.TryGet(LogEventLevel.Verbose, LogArea.AndroidPlatform)?.Log(this, "Content URI was virtual: '{Uri}'", uri);
return GetVirtualFileStream(context, uri, isOutput);
}
return isOutput
? context.ContentResolver?.OpenOutputStream(uri, "wt")
: context.ContentResolver?.OpenInputStream(uri);
}
View on GitHub (pinned to 11c5427268)
Solutions
- Verify takePersistableUriPermission was called and the FLAG_GRANT_READ_URI_PERMISSION persisted before using the bookmark.
- Catch InvalidOperationException (or the underlying null) and re-prompt the user to re-pick the file when the URI is stale.
- For virtual files, ensure the device/provider can produce the requested representation; fall back to a different MIME type.
- Check AndroidStorageFile existence via GetItemAsync/DocumentsContract before opening.
Example fix
// before
using var stream = file.OpenRead();
// after
try
{
using var stream = file.OpenRead();
// read
}
catch (InvalidOperationException)
{
// permission revoked or file gone — re-prompt
await ReRequestFileAccess();
} Defensive patterns
Strategy: try-catch
Validate before calling
// verify the URI is still resolvable before opening for read var info = await DocumentsContract.GetDocumentMetadata(Activity.ContentResolver, file.Uri); if (info is null) return; // stale or permission lost
Try / catch
try { using var s = file.OpenRead(); /* read */ }
catch (InvalidOperationException) { /* permission revoked or file gone */ await ReRequestFileAccess(); } Prevention
- Persist read permission via takePersistableUriPermission with FLAG_GRANT_READ_URI_PERMISSION.
- Re-prompt the user when a bookmarked URI becomes stale.
- For virtual/cloud files, confirm the requested representation is available.
- Check document existence before opening.
When it happens
Trigger: Calling OpenRead()/OpenReadAsync() on an AndroidStorageFile whose URI can no longer be opened: the persistent permission was revoked, the underlying document was deleted/moved, the file is virtual and the alternate stream MIME type produced no stream, or ContentResolver is unavailable.
Common situations: Persisted bookmarks across app restarts where the user revoked SAF permission or the file was deleted; accessing content from another app that has since been uninstalled; virtual documents (e.g. Google Drive) whose alternate representation isn't available offline; transient provider errors on certain OEMs.
Related errors
- Can not create '{name}' because a directory with the same na
- Can not create '{name}' because a file with the same name al
- result.GetStringExtra("error")
- File path is expected to be an absolute link with "file" or
- Folder path is expected to be an absolute link with "file" o
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/4b21d094d74c70e0.
Report an issue: GitHub.