beemdevelopment/Aegis · error · IOException
Unable to create directory
Error message
Unable to create directory %s
What it means
scheduleBackup stages the vault into <cacheDir>/backup before handing it to VaultBackupManager. If the directory does not exist and File.mkdir() fails, it throws an IOException('Unable to create directory %s'). mkdir() fails only when the parent is missing or a filesystem error occurs (permissions, disk full, I/O error).
Solutions
- Check free space and clear app cache (or Settings > Storage) so cache writes succeed, then retry the backup
- Use mkdirs() and tolerate 'already exists' instead of bare mkdir() so a stale file/race doesn't abort: if (!dir.exists() && !dir.isDirectory() && !dir.mkdirs()) throw ...
- Restart the app to reinitialize a healthy cache directory if the cache dir is in a bad state
- Investigate SELinux/ROM restrictions if mkdir consistently fails on this device profile
Example fix
// before
File dir = new File(_context.getCacheDir(), "backup");
if (!dir.exists() && !dir.mkdir()) {
throw new IOException(String.format("Unable to create directory %s", dir));
}
// after
File dir = new File(_context.getCacheDir(), "backup");
if (!dir.isDirectory() && !dir.mkdirs()) {
throw new IOException(String.format("Unable to create directory %s", dir));
} Defensive patterns
Strategy: try-catch
Validate before calling
File dir = new File(context.getCacheDir(), "backup");
if (!dir.isDirectory() && !dir.mkdirs()) {
Log.e(TAG, "cannot create " + dir + "; free space: " + dir.getUsableSpace());
} Type guard
boolean canStageBackup(Context ctx) {
File dir = new File(ctx.getCacheDir(), "backup");
return (dir.isDirectory() || dir.mkdirs()) && dir.getUsableSpace() > MIN_BACKUP_BYTES;
} Try / catch
try {
vaultManager.scheduleBackup();
} catch (VaultRepositoryException e) {
if (e.getCause() instanceof IOException && e.getMessage().contains("Unable to create directory")) {
notifyStorageProblem();
}
} Prevention
- Check usable space before backup scheduling
- Use mkdirs() and treat pre-existing dirs as success
- Don't race cache cleaners with backup jobs (use WorkManager constraints)
When it happens
Trigger: cacheDir/backup cannot be created: app cache storage unreadable/wiped concurrently, disk full, read-only filesystem, or a non-directory file named 'backup' already occupies the path (mkdir returns false for existing non-dir).
Common situations: Device storage full; OEM cache cleaners racing the backup; broken cache state after restore; tests/emulators with restricted storage.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- Unable to create directories
- Unable to delete directory
- Unable to create directory
- Backup file already exists
- createFile returned null
AI-assisted analysis of beemdevelopment/Aegis@d6f4e5925a (2026-09-08).
Data as JSON: /api/errors/b1c7661194613bd1.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/com/beemdevelopment/aegis/vault/VaultManager.java:170
if (_prefs.isAndroidBackupsEnabled()) {
backedUp = true;
scheduleAndroidBackup();
}
}
if (!backedUp) {
_prefs.setIsBackupReminderNeeded(true);
}
}
public void scheduleBackup() throws VaultRepositoryException {
_prefs.setIsBackupReminderNeeded(false);
try {
File dir = new File(_context.getCacheDir(), "backup");
if (!dir.exists() && !dir.mkdir()) {
throw new IOException(String.format("Unable to create directory %s", dir));
}
File tempFile = File.createTempFile(VaultBackupManager.FILENAME_PREFIX, ".json", dir);
try (OutputStream outStream = new FileOutputStream(tempFile)) {
_repo.export(outStream);
}
BackupsVersioningStrategy strategy = _prefs.getBackupVersioningStrategy();
Uri uri = _prefs.getBackupsLocation();
int versionsToKeep = _prefs.getBackupsVersionCount();
_backups.scheduleBackup(tempFile, strategy, uri, versionsToKeep);
} catch (IOException e) {
throw new VaultRepositoryException(e);
}
}
public void scheduleAndroidBackup() {
_prefs.setIsBackupReminderNeeded(false);View on GitHub (pinned to d6f4e5925a)