yuliskov/SmartTube · error · IllegalStateException
Failed to copyUriToFile
Error message
Failed to copyUriToFile
What it means
copyUriToFile streams a SAF content Uri (the user-picked backup file) into a local file during backup/restore; any exception from open/read/write/close is printStackTrace'd and rethrown as IllegalStateException("Failed to copyUriToFile") with the original error as cause. The cause chain — FileNotFoundException, SecurityException, ENOSPC — is the actual diagnosis; the wrapper only says the copy step failed.
Source
Thrown at common/src/main/java/com/liskovsoft/smartyoutubetv2/common/misc/BackupAndRestoreHelper.java:271
}
private void copyUriToFile(Uri uri, File outFile) {
try {
InputStream in = mContext.getContentResolver().openInputStream(uri);
OutputStream out = new FileOutputStream(outFile);
byte[] buffer = new byte[8192];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
in.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
throw new IllegalStateException("Failed to copyUriToFile", e);
}
}
private String getFileName(Uri uri) {
Cursor cursor = mContext.getContentResolver().query(uri, null, null, null, null);
if (cursor != null) {
int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
cursor.moveToFirst();
String name = cursor.getString(nameIndex);
cursor.close();
return name;
}
return null;
}
private GeneralData getGeneralData() {
return GeneralData.instance(mContext);
}
View on GitHub (pinned to 3de8d90593)
Solutions
- Unwrap the cause: SecurityException means permission, FileNotFoundException means a stale Uri, IOException with ENOSPC means space
- Re-pick the file with ACTION_OPEN_DOCUMENT and call takePersistableUriPermission where the flow allows
- Check the source document exists and free space is sufficient before copying
- Isolate per-item failures in the backup loop so one bad file does not abort the whole run
Example fix
// before
// restore path uses an old persisted Uri whose grant was lost on reinstall
copyUriToFile(context, oldUri, targetFile); // throws
// after
Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT);
// ... in onActivityResult:
context.getContentResolver().takePersistableUriPermission(uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION); Defensive patterns
Strategy: try-catch
Validate before calling
DocumentFile doc = DocumentFile.fromSingleUri(context, uri);
if (doc == null || !doc.exists() || !doc.canRead()) {
// ask the user to re-pick the file instead of copying
}
// also check free space on the target directory before copying Try / catch
try {
copyUriToFile(context, uri, target);
} catch (IllegalStateException e) {
Throwable cause = e.getCause() != null ? e.getCause() : e;
if (cause instanceof SecurityException || cause instanceof FileNotFoundException) {
// stale grant: prompt re-pick, continue with remaining backup items
} else {
// log cause and abort this item
}
} Prevention
- Call takePersistableUriPermission immediately after ACTION_OPEN_DOCUMENT results
- Verify exists()/canRead() and free space before copying
- Structure backup loops so one failed item skips rather than aborts the run
When it happens
Trigger: The Uri read permission is missing or expired (ACTION_OPEN_DOCUMENT result used after the grant lapsed, takePersistableUriPermission never called); the source file was deleted or renamed between selection and copy; disk full or target path unwritable mid-write; ContentResolver.openInputStream returning null for the Uri.
Common situations: Restore flows reusing a persisted Uri after app reinstall (grants reset); backup file on removable storage that unmounted during the copy; device storage exhausted mid-backup.
Related errors
- You can't set adapter to DialogsList. Use #setAdapter(Dialog
- You can't set adapter to MessagesList. Use #setAdapter(Messa
- You must pass either Activity, Fragment or SupportFragment
- You must pass Activity/Fragment by calling withActivity/with
- Unknown Uri: ${uri}
AI-assisted analysis of yuliskov/SmartTube@3de8d90593 (2026-08-22).
Data as JSON: /api/errors/06e07b8f4037efef.
Report an issue: GitHub.