beemdevelopment/Aegis · error · IOException

Unable to create directory

Error message

Unable to create directory %s

What it means

ImportExportPreferencesFragment.getExportCacheDir() creates a 'export' subdirectory inside the app cache dir before writing an export file. If the directory does not exist and File.mkdir() fails (returns false), it throws an IOException with the directory path. Called by startExport and onExportResult when preparing vault exports.

Solutions

  1. Free up device storage and retry the export
  2. Clear the app's cache (Settings > Apps > Aegis > Storage > Clear cache) and retry
  3. Reboot the device to release file locks, then retry the export
  4. If it persists, reinstall the app (after backing up the vault) to reset the cache directory state

Example fix

// before
if (!dir.exists() && !dir.mkdir()) {
    throw new IOException(String.format("Unable to create directory %s", dir));
}
// after
if (!dir.exists() && !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(requireContext().getCacheDir(), "export");
if (!dir.exists() && !dir.isDirectory() && requireContext().getCacheDir().getUsableSpace() < requiredBytes) {
    // prompt user to free storage before exporting
}

Try / catch

try {
    startExport(requestCode, cb, filter);
} catch (IOException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Unable to create directory")) {
        // show storage-full/clear-cache guidance to the user
    }
}

Prevention

When it happens

Trigger: Invoking startExport/onExportResult on a device where cache dir creation fails — typically storage full, the cache path exists as a file, or a transient filesystem/permission problem prevents mkdir().

Common situations: Devices with full internal storage, corrupted cache directories, restricted app storage after OEM 'cleaner' apps interfering, or concurrent export attempts racing on the same path.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of beemdevelopment/Aegis@d6f4e5925a (2026-09-08). Data as JSON: /api/errors/ae9ba4965e369121. Report an issue: GitHub.

Appendix: source

Thrown at app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/ImportExportPreferencesFragment.java:436

            return new VaultBackupManager.FileInfo(VaultRepository.FILENAME_PREFIX_EXPORT_HTML, "html");
        }

        return new VaultBackupManager.FileInfo(VaultRepository.FILENAME_PREFIX_EXPORT_URI, "txt");
    }

    private static String getExportMimeType(int requestCode) {
        if (requestCode == CODE_EXPORT_GOOGLE_URI) {
            return "text/plain";
        } else if (requestCode == CODE_EXPORT_HTML) {
            return "text/html";
        }
        return "application/json";
    }

    private File getExportCacheDir() throws IOException {
        File dir = new File(requireContext().getCacheDir(), "export");
        if (!dir.exists() && !dir.mkdir()) {
            throw new IOException(String.format("Unable to create directory %s", dir));
        }

        return dir;
    }

    private void startExportVault(int requestCode, StartExportCallback cb, @Nullable Vault.EntryFilter filter) {
        switch (requestCode) {
            case CODE_EXPORT:
                if (_vaultManager.getVault().isEncryptionEnabled()) {
                    cb.exportVault(stream -> {
                        if (filter != null) {
                            _vaultManager.getVault().exportFiltered(stream, filter);
                        } else {
                            _vaultManager.getVault().export(stream);
                        }
                    });
                } else {
                    Dialogs.showSetPasswordDialog(requireActivity(), new Dialogs.PasswordSlotListener() {

View on GitHub (pinned to d6f4e5925a)