TeamNewPipe/NewPipe · error · IOException

SAF not available

Error message

SAF not available

What it means

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.

Source

Thrown at app/src/main/java/org/schabi/newpipe/streams/io/StoredFileHelper.java:133

        sourceTree = Uri.fromFile(location.toFile()).toString();

        srcName = ioPath.getFileName().toString();
        srcType = mime;
    }

    public StoredFileHelper(final Context context, @Nullable final Uri parent,
                            @NonNull final Uri path, final String tag) throws IOException {
        this.tag = tag;
        this.source = path.toString();

        if (path.getScheme() == null
                || path.getScheme().equalsIgnoreCase(ContentResolver.SCHEME_FILE)) {
            this.ioPath = Paths.get(URI.create(this.source));
        } else {
            final DocumentFile file = DocumentFile.fromSingleUri(context, path);

            if (file == null) {
                throw new IOException("SAF not available");
            }

            this.context = context;

            if (file.getName() == null) {
                this.source = null;
                return;
            } else {
                this.docFile = file;
                takePermissionSAF();
            }
        }

        if (parent != null) {
            if (!ContentResolver.SCHEME_FILE.equals(parent.getScheme())) {
                this.docTree = DocumentFile.fromTreeUri(context, parent);
            }

View on GitHub (pinned to 9e8be09156)

Solutions

  1. 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.
  2. Use the URI immediately (within the activity's lifecycle) rather than persisting a single-document URI.
  3. Catch the IOException and prompt the user to re-select the file.
  4. For file:// URIs this branch is skipped; if you control the source, prefer file:// paths for transient access.
Defensive patterns

Strategy: validation

Validate before calling

// Before constructing StoredFileHelper for a single URI:
DocumentFile df = DocumentFile.fromSingleUri(context, path);
if (df == null) {
    // provider unavailable — do not pass to constructor
    throw new FileNotFoundException("No DocumentsProvider for URI: " + path);
}

Try / catch

try {
    StoredFileHelper helper = new StoredFileHelper(context, parent, path, tag);
} catch (IOException e) {
    if ("SAF not available".equals(e.getMessage())) {
        // URI's provider is gone — ask user to re-select file
        promptForFileReSelection();
    } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of TeamNewPipe/NewPipe@9e8be09156 (2026-08-14). Data as JSON: /api/errors/a9a929cd739229fc. Report an issue: GitHub.