{"record":{"id":"589d9cdb77528c7f","repo":"AvaloniaUI/Avalonia","slug":"result-getstringextra-error","errorCode":null,"errorMessage":"result.GetStringExtra(\"error\")","messagePattern":"result\\.GetStringExtra\\(\"error\"\\)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs","lineNumber":261,"sourceCode":"            {\n                for (var i = 0; i < clipData.ItemCount; i++)\n                {\n                    var uri = clipData.GetItemAt(i)?.Uri;\n                    if (uri != null)\n                    {\n                        resultList.Add(uri);\n                    }\n                }\n            }\n            else if (result.Data is { } uri)\n            {\n                resultList.Add(uri);\n            }\n        }\n\n        if (result?.HasExtra(\"error\") == true)\n        {\n            throw new Exception(result.GetStringExtra(\"error\"));\n        }\n\n        return resultList;\n\n        void OnActivityResult(int requestCode, Result resultCode, Intent? data)\n        {\n            if (currentRequestCode != requestCode)\n            {\n                return;\n            }\n\n            mainActivity.ActivityResult -= OnActivityResult;\n\n            _ = tcs.TrySetResult(resultCode == Result.Ok ? data : null);\n        }\n    }\n\n    private static Intent TryAddExtraInitialUri(Intent intent, IStorageFolder? folder)","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs#L243-L279","documentation":"Thrown after a storage picker Activity returns when the result Intent carries an extra keyed \"error\" (result.HasExtra(\"error\") == true). Avalonia re-throws the picker provider's error string verbatim as a generic Exception. The actual message is whatever the document/picker provider placed in the \"error\" extra (security errors, provider unavailable, picker canceled with error, etc.).","triggerScenarios":"A SAF/document picker returns an Intent whose extras include \"error\". The content is provider-specific: could be a permission denial, an unsupported action, an OEM picker bug, or the picker failing to produce a URI.","commonSituations":"OEM picker returning an error extra instead of a null result; permissions issues on scoped storage; provider (cloud/office) that signals errors via extras; edge cases on specific Android versions where the picker returns both no URI and an error string.","solutions":["Wrap picker calls (OpenFilePicker, SaveFilePicker, OpenFolderPicker) in try/catch and surface the embedded error message to the user.","Inspect the exception's Message (it is the provider's error string) to decide whether to retry or guide the user.","Verify storage permissions and SAF access before invoking the picker; if the error is permission-related, request access.","On repeated failures on a specific device/OEM, offer a fallback (e.g. system file chooser via ACTION_OPEN_DOCUMENT)."],"exampleFix":"// before\nvar files = await storageProvider.OpenFilePickerAsync(options);\n\n// after\ntry\n{\n    var files = await storageProvider.OpenFilePickerAsync(options);\n}\ncatch (Exception ex) when (ex.Message != null)\n{\n    await ShowUser($\"Picker error: {ex.Message}\");\n}","handlingStrategy":"try-catch","validationCode":"// no pre-check is possible — the error comes from the picker result extra.\n// ensure permissions are in place before launching to reduce error likelihood.\nif (activity is not IActivityResultHandler) throw new InvalidOperationException(\"Activity must be an IActivityResultHandler\");","typeGuard":null,"tryCatchPattern":"try { return await storageProvider.OpenFilePickerAsync(options); }\ncatch (Exception ex) { await ShowUser($\"Picker error: {ex.Message}\"); return Array.Empty<IStorageFile>(); }","preventionTips":["Wrap picker calls in try/catch and surface the embedded error string.","Verify SAF/storage permissions before invoking the picker.","Offer fallbacks (ACTION_OPEN_DOCUMENT) for OEM-specific failures.","Inspect ex.Message to classify permission vs provider errors."],"tags":["android","storage","picker","saf","error-propagation"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}