{"record":{"id":"4b21d094d74c70e0","repo":"AvaloniaUI/Avalonia","slug":"failed-to-open-content-stream","errorCode":null,"errorMessage":"Failed to open content stream","messagePattern":"Failed to open content stream","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs","lineNumber":484,"sourceCode":"    public WellKnownAndroidStorageFolder(Activity activity, string identifier, AndroidUri uri, bool needsExternalFilesPermission)\n        : base(activity, uri, needsExternalFilesPermission)\n    {\n        Name = identifier;\n    }\n\n    public override string Name { get; }\n}\n\ninternal sealed class AndroidStorageFile : AndroidStorageItem, IStorageBookmarkFile\n{\n    public AndroidStorageFile(Activity activity, AndroidUri uri, AndroidStorageFolder? parent = null, AndroidUri? permissionRoot = null) : base(activity, uri, false, parent, permissionRoot)\n    {\n    }\n\n    public Task<Stream> OpenReadAsync() => Task.FromResult(OpenRead());\n\n    public Stream OpenRead() => OpenContentStream(Activity, Uri, false)\n        ?? throw new InvalidOperationException(\"Failed to open content stream\");\n\n    public Task<Stream> OpenWriteAsync() => Task.FromResult(OpenContentStream(Activity, Uri, true)\n        ?? throw new InvalidOperationException(\"Failed to open content stream\"));\n\n    private Stream? OpenContentStream(Context context, AndroidUri uri, bool isOutput)\n    {\n        var isVirtual = IsVirtualFile(context, uri);\n        if (isVirtual)\n        {\n            Logger.TryGet(LogEventLevel.Verbose, LogArea.AndroidPlatform)?.Log(this, \"Content URI was virtual: '{Uri}'\", uri);\n            return GetVirtualFileStream(context, uri, isOutput);\n        }\n\n        return isOutput\n            ? context.ContentResolver?.OpenOutputStream(uri, \"wt\")\n            : context.ContentResolver?.OpenInputStream(uri);\n    }\n","sourceCodeStart":466,"sourceCodeEnd":502,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs#L466-L502","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nusing var stream = file.OpenRead();\n\n// after\ntry\n{\n    using var stream = file.OpenRead();\n    // read\n}\ncatch (InvalidOperationException)\n{\n    // permission revoked or file gone — re-prompt\n    await ReRequestFileAccess();\n}","handlingStrategy":"try-catch","validationCode":"// verify the URI is still resolvable before opening for read\nvar info = await DocumentsContract.GetDocumentMetadata(Activity.ContentResolver, file.Uri);\nif (info is null) return; // stale or permission lost","typeGuard":null,"tryCatchPattern":"try { using var s = file.OpenRead(); /* read */ }\ncatch (InvalidOperationException) { /* permission revoked or file gone */ await ReRequestFileAccess(); }","preventionTips":["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."],"tags":["android","storage","io","contentresolver","saf","read"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}