{"record":{"id":"95a4f889c19a179a","repo":"AvaloniaUI/Avalonia","slug":"file-path-is-expected-to-be-an-absolute-link-with","errorCode":null,"errorMessage":"File path is expected to be an absolute link with \"file\" or \"content\" scheme.","messagePattern":"File path is expected to be an absolute link with \"file\" or \"content\" scheme\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs","lineNumber":49,"sourceCode":"\n    public bool CanPickFolder => OperatingSystem.IsAndroidVersionAtLeast(21);\n\n    public Task<IStorageBookmarkFolder?> OpenFolderBookmarkAsync(string bookmark)\n    {\n        var uri = DecodeUriFromBookmark(bookmark);\n        return Task.FromResult<IStorageBookmarkFolder?>(uri is null ? null : new AndroidStorageFolder(_activity, uri, false));\n    }\n\n    public async Task<IStorageFile?> TryGetFileFromPathAsync(Uri filePath)\n    {\n        if (filePath is null)\n        {\n            throw new ArgumentNullException(nameof(filePath));\n        }\n\n        if (filePath is not { IsAbsoluteUri: true, Scheme: \"file\" or \"content\" })\n        {\n            throw new ArgumentException(\"File path is expected to be an absolute link with \\\"file\\\" or \\\"content\\\" scheme.\");\n        }\n\n        var androidUri = AndroidUri.Parse(filePath.ToString());\n        if (androidUri?.Path is not {} androidUriPath)\n        {\n            return null;\n        }\n\n        // About the READ_EXTERNAL_STORAGE permission:\n        // https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE\n        //  - \"Starting in API level 33, this permission has no effect.\"\n        //  - \"Also starting in API level 19, this permission is not required\n        //     to read or write files in your application-specific directories [...]\"\n        // Consequently, we don't try to check for that permission here anymore.\n\n        var javaFile = new JavaFile(androidUriPath);\n        if (javaFile.Exists() && javaFile.IsFile)\n        {","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs#L31-L67","documentation":"Thrown by AndroidStorageProvider.TryGetFileFromPathAsync when the supplied Uri is not absolute, or its Scheme is neither \"file\" nor \"content\". On Android, Avalonia can only resolve storage items via the file:// or content:// URI schemes that the Storage Access Framework and filesystem understand.","triggerScenarios":"Calling TryGetFileFromPathAsync with a relative Uri, or an absolute Uri using an unsupported scheme (e.g. http://, ftp://, custom://, or a bare path string wrapped via new Uri(path) which may produce a relative Uri depending on escaping).","commonSituations":"Passing a raw filesystem path string instead of a file:// URI; receiving a path from cross-platform code that uses a different scheme; UriKind issues where new Uri(value) defaults to relative for some inputs; sharing a URI from another platform (desktop/iOS) into the Android provider.","solutions":["Construct the URI explicitly as absolute with the correct scheme: new Uri(filePath, UriKind.Absolute) where filePath starts with file:// or content://.","If you have a bare filesystem path, wrap it: new Uri(new System.IO.FileInfo(path).FullName) or build file:// manually.","Validate Uri.IsAbsoluteUri and Uri.Scheme before calling TryGetFileFromPathAsync and reject/convert unsupported schemes upstream.","For content URIs from intents/pickers, pass them through directly without re-parsing into a different scheme."],"exampleFix":"// before\nvar file = await provider.TryGetFileFromPathAsync(new Uri(\"/sdcard/doc.txt\"));\n\n// after\nvar path = System.IO.Path.GetFullPath(\"/sdcard/doc.txt\");\nvar file = await provider.TryGetFileFromPathAsync(new Uri($\"file://{path}\"));","handlingStrategy":"validation","validationCode":"// validate scheme before calling the provider\nif (filePath is not { IsAbsoluteUri: true } || (filePath.Scheme != \"file\" && filePath.Scheme != \"content\"))\n    throw new ArgumentException(\"Use an absolute file:// or content:// URI.\");\nvar file = await provider.TryGetFileFromPathAsync(filePath);","typeGuard":"static bool IsValidAndroidStorageUri(Uri? u) => u is { IsAbsoluteUri: true } && (u.Scheme == \"file\" || u.Scheme == \"content\");","tryCatchPattern":null,"preventionTips":["Always build absolute file:// or content:// URIs.","Wrap raw filesystem paths with file:// via Path.GetFullPath.","Validate IsAbsoluteUri and Scheme before calling the provider.","Forward content:// URIs from pickers verbatim."],"tags":["android","storage","uri","validation","scheme"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}