MuntashirAkon/AppManager · error · FileNotFoundException
Couldn't find any writable Obb dir
Error message
Couldn't find any writable Obb dir
What it means
getWritableExternalDirectory iterates candidate external storage directories and throws FileNotFoundException when none is writable (or on /storage/emulated). It is used by obbDir() to locate a directory where OBB files can be written; without a writable external dir, OBB installation cannot proceed.
Source
Thrown at app/src/main/java/io/github/muntashirakon/AppManager/apk/ApkUtils.java:312
.findOrCreateDirectory("obb")
.findOrCreateDirectory(packageName);
return Paths.get(obbDir.getUri());
}
@NonNull
public static Path getWritableExternalDirectory(@UserIdInt int userId) throws FileNotFoundException {
// Get the first writable external storage directory
OsEnvironment.UserEnvironment userEnvironment = OsEnvironment.getUserEnvironment(userId);
Path[] extDirs = userEnvironment.getExternalDirs();
Path writableExtDir = null;
for (Path extDir : extDirs) {
if (extDir.canWrite() || Objects.requireNonNull(extDir.getFilePath()).startsWith("/storage/emulated")) {
writableExtDir = extDir;
break;
}
}
if (writableExtDir == null) {
throw new FileNotFoundException("Couldn't find any writable Obb dir");
}
return writableExtDir;
}
public static int getDensityFromName(@Nullable String densityName) {
Integer density = StaticDataset.DENSITY_NAME_TO_DENSITY.get(densityName);
if (density == null) {
throw new IllegalArgumentException("Unknown density " + densityName);
}
return density;
}
@NonNull
private static ByteBuffer getAndroidManifestFromApk(
@NonNull List<CentralDirectoryRecord> cdRecords, @NonNull DataSource lhfSection)
throws IOException, ApkFormatException, ZipFormatException {
CentralDirectoryRecord androidManifestCdRecord = findCdRecord(cdRecords, MANIFEST_FILE);
if (androidManifestCdRecord == null) {View on GitHub (pinned to 0152f468fc)
Solutions
- Grant storage permissions (MANAGE_EXTERNAL_STORAGE on Android 11+, or READ/WRITE_EXTERNAL_STORAGE with legacy storage) before calling obbDir().
- Check that at least one external storage volume is mounted and writable via Environment.getExternalStorageState().
- Fall back to app-private storage (context.getExternalFilesDirs or getObbDirs) and handle the exception by copying OBB data there.
- Wrap obbDir() in try-catch for FileNotFoundException and surface a user-facing 'no writable storage' message.
Example fix
// before
File obbDir = ApkUtils.obbDir();
// after
File obbDir;
try {
obbDir = ApkUtils.obbDir();
} catch (FileNotFoundException e) {
obbDir = context.getExternalFilesDir(null); // fallback
} Defensive patterns
Strategy: fallback
Validate before calling
boolean hasWritable = Arrays.stream(context.getExternalFilesDirs(null))
.anyMatch(d -> d != null && d.canWrite());
if (!hasWritable) requestStoragePermissionsOrAbort(); Try / catch
try {
File obbDir = ApkUtils.obbDir();
} catch (FileNotFoundException e) {
File fallback = context.getExternalFilesDir(null);
} Prevention
- Request MANAGE_EXTERNAL_STORAGE / legacy storage permissions before OBB operations.
- Check Environment.getExternalStorageState() equals MEDIA_MOUNTED before use.
- Design for scoped storage (Android 11+): prefer app-specific dirs over shared external storage.
- Test on devices with adopted storage and no SD card.
When it happens
Trigger: Calling ApkUtils.obbDir() when every enumerated external directory is read-only or not under /storage/emulated — e.g. fully adopted storage, restricted storage permissions, or scoped-storage restrictions on Android 11+ where no writable external dir is found.
Common situations: Running on devices with no SD card and denied MANAGE_EXTERNAL_STORAGE/READ_WRITE permissions, Android 11+ scoped storage restricting OBB paths, emulators with unusual storage layouts, or work-profile/restricted users.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Could not create cache. Is this OS broken?
- Could not delete the selected backups
- Could not create package staging directory
- Could not create staging files
- Failed to access properties of the KeyStore folder.
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/22ee9aedac79c052.
Report an issue: GitHub.