beemdevelopment/Aegis · error · IOException
openOutputStream returned null
Error message
openOutputStream returned null
What it means
Guard in VaultBackupManager.createBackup(File, Uri): thrown as VaultRepositoryException when ContentResolver.openOutputStream(fileUri) returns null, meaning the provider accepted the URI but cannot supply a writable stream (destination removed or locked). The backup attempt fails and scheduleBackup records the error in Preferences.BackupResult for the UI.
Solutions
- Null-check the OutputStream returned by ContentResolver.openOutputStream(fileUri, "wt") and throw VaultRepositoryException naming the backup Uri
- Verify hasPermissionsAt(fileUri) passed and the Uri still resolves (query it) before opening the output stream
- Retry once with mode "w" if openOutputStream returns null for "wt", since some providers do not support truncation mode
- Catch SecurityException from openOutputStream and convert it to VaultBackupPermissionException so the user is prompted to re-grant access
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at app/src/main/java/com/beemdevelopment/aegis/vault/VaultBackupManager.java:96 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of beemdevelopment/Aegis@d6f4e5925a (2026-09-08).
Data as JSON: /api/errors/61b50831c3faf384.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/com/beemdevelopment/aegis/vault/VaultBackupManager.java:96
createBackup(tempFile, uri, versionsToKeep);
} else {
throw new VaultRepositoryException("Invalid backups versioning strategy");
}
}
private void createBackup(File tempFile, Uri fileUri)
throws VaultRepositoryException, VaultBackupPermissionException {
Log.i(TAG, String.format("Creating backup at %s", fileUri));
try {
if (!hasPermissionsAt(fileUri)) {
throw new VaultBackupPermissionException("No persisted URI permissions");
}
ContentResolver resolver = _context.getContentResolver();
try (FileInputStream inStream = new FileInputStream(tempFile);
OutputStream outStream = resolver.openOutputStream(fileUri, "wt")
) {
if (outStream == null) {
throw new IOException("openOutputStream returned null");
}
IOUtils.copy(inStream, outStream);
} catch (IOException exception) {
throw new VaultRepositoryException(exception);
}
} catch (VaultRepositoryException | VaultBackupPermissionException exception) {
Log.e(TAG, String.format("Unable to create backup: %s", exception));
throw exception;
} finally {
tempFile.delete();
}
}
private void createBackup(File tempFile, Uri dirUri, int versionsToKeep)
throws VaultRepositoryException, VaultBackupPermissionException {
FileInfo fileInfo = new FileInfo(FILENAME_PREFIX);
DocumentFile dir = DocumentFile.fromTreeUri(_context, dirUri);
View on GitHub (pinned to d6f4e5925a)