{"record":{"id":"a9a929cd739229fc","repo":"TeamNewPipe/NewPipe","slug":"saf-not-available","errorCode":null,"errorMessage":"SAF not available","messagePattern":"SAF not available","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/org/schabi/newpipe/streams/io/StoredFileHelper.java","lineNumber":133,"sourceCode":"        sourceTree = Uri.fromFile(location.toFile()).toString();\n\n        srcName = ioPath.getFileName().toString();\n        srcType = mime;\n    }\n\n    public StoredFileHelper(final Context context, @Nullable final Uri parent,\n                            @NonNull final Uri path, final String tag) throws IOException {\n        this.tag = tag;\n        this.source = path.toString();\n\n        if (path.getScheme() == null\n                || path.getScheme().equalsIgnoreCase(ContentResolver.SCHEME_FILE)) {\n            this.ioPath = Paths.get(URI.create(this.source));\n        } else {\n            final DocumentFile file = DocumentFile.fromSingleUri(context, path);\n\n            if (file == null) {\n                throw new IOException(\"SAF not available\");\n            }\n\n            this.context = context;\n\n            if (file.getName() == null) {\n                this.source = null;\n                return;\n            } else {\n                this.docFile = file;\n                takePermissionSAF();\n            }\n        }\n\n        if (parent != null) {\n            if (!ContentResolver.SCHEME_FILE.equals(parent.getScheme())) {\n                this.docTree = DocumentFile.fromTreeUri(context, parent);\n            }\n","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/TeamNewPipe/NewPipe/blob/9e8be091560a69f35d44bd252eb00bc7911c977b/app/src/main/java/org/schabi/newpipe/streams/io/StoredFileHelper.java#L115-L151","documentation":"Thrown when StoredFileHelper is constructed for a single (non-file-scheme) URI: the URI's scheme is not 'file', so the constructor goes the SAF route via DocumentFile.fromSingleUri(context, path). If that returns null the constructor throws 'SAF not available'. fromSingleUri returns null when the ContentResolver cannot find a DocumentsProvider for the URI authority, indicating the URI does not point to an accessible document.","triggerScenarios":"StoredFileHelper(context, parent, path, tag) is called with a content:// URI whose authority/provider is not registered or not available; DocumentFile.fromSingleUri returns null. Occurs when the URI was not obtained from ACTION_OPEN_DOCUMENT/CREATE_DOCUMENT or the provider app is gone.","commonSituations":"Sharing/importing a content URI from an app that was since uninstalled; a URI passed across process boundaries without the proper persistable permission grant; a URI with an unregistered custom scheme-authority pair; restoring a saved content URI after the source app was cleared.","solutions":["Ensure the URI was obtained from a SAF intent (ACTION_OPEN_DOCUMENT) and the permission was taken with takePersistableUriPermission if it must survive beyond the current task.","Use the URI immediately (within the activity's lifecycle) rather than persisting a single-document URI.","Catch the IOException and prompt the user to re-select the file.","For file:// URIs this branch is skipped; if you control the source, prefer file:// paths for transient access."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before constructing StoredFileHelper for a single URI:\nDocumentFile df = DocumentFile.fromSingleUri(context, path);\nif (df == null) {\n    // provider unavailable — do not pass to constructor\n    throw new FileNotFoundException(\"No DocumentsProvider for URI: \" + path);\n}","typeGuard":null,"tryCatchPattern":"try {\n    StoredFileHelper helper = new StoredFileHelper(context, parent, path, tag);\n} catch (IOException e) {\n    if (\"SAF not available\".equals(e.getMessage())) {\n        // URI's provider is gone — ask user to re-select file\n        promptForFileReSelection();\n    } else throw e;\n}","preventionTips":["Take persistable URI permission immediately after ACTION_OPEN_DOCUMENT returns.","Do not persist single-document content URIs across app reinstalls.","If you only need transient access, consume the URI within the same activity lifecycle."],"tags":["android-saf","storage","documentfile","uri-permission","io"],"backgroundTag":null,"analyzedSha":"9e8be091560a69f35d44bd252eb00bc7911c977b","analyzedAt":"2026-08-14T00:11:33.519Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}