MuntashirAkon/AppManager · error · FileNotFoundException
Shared storage unavailable.
Error message
Shared storage unavailable.
What it means
getBestExternalDataSubdir scans the device's array of app-specific external storage directories and returns the first usable one. It throws FileNotFoundException("Shared storage unavailable.") when the extDirs array itself is null, meaning the OS reported no external/shared storage at all (Context#getExternalFilesDirs returned null). The method never returns null; callers like getExternalCachePath propagate this failure.
Source
Thrown at app/src/main/java/io/github/muntashirakon/AppManager/utils/FileUtils.java:187
Context context = ContextUtils.getContext();
try {
return getExternalCachePath(context);
} catch (FileNotFoundException e) {
return context.getCacheDir();
}
}
@AnyThread
@NonNull
public static File getExternalCachePath(@NonNull Context context) throws FileNotFoundException {
return getBestExternalDataSubdir(context.getExternalCacheDirs());
}
@AnyThread
@NonNull
public static File getBestExternalDataSubdir(@Nullable File[] extDirs) throws FileNotFoundException {
if (extDirs == null) {
throw new FileNotFoundException("Shared storage unavailable.");
}
String lastReason = null;
for (File extDir : extDirs) {
// The priority is from top to bottom of the list as per Context#getExternalDir()
if (extDir == null) {
// Other external directory might exist
continue;
}
if (!(extDir.exists() || extDir.mkdirs())) {
// Try to recreate this with root
if (RunnerUtils.isRootGiven() && forceCreateExternalDataSubDir(extDir)) {
Log.i(TAG, "Root created %s", extDir);
return extDir;
}
lastReason = extDir + ": permission denied.";
Log.w(TAG, "Could not use %s.", extDir);
continue;
}View on GitHub (pinned to 0152f468fc)
Solutions
- Check extDirs != null (or catch FileNotFoundException) before relying on external storage and fall back to internal Context#getCacheDir/getFilesDir
- Verify external storage is mounted via Environment.getExternalStorageState() before calling
- Avoid calling storage APIs before the device finishes booting (check Environment.getExternalStorageState / boot-completed)
- On restricted profiles, grant or verify storage access for the calling user
Example fix
// before
File dir = FileUtils.getBestExternalDataSubdir(extDirs);
// after
File dir;
try {
dir = FileUtils.getBestExternalDataSubdir(extDirs);
} catch (FileNotFoundException e) {
dir = context.getCacheDir(); // fall back to internal storage
} Defensive patterns
Strategy: fallback
Validate before calling
File[] extDirs = context.getExternalFilesDirs(null);
if (extDirs == null || Arrays.stream(extDirs).filter(Objects::nonNull).findAny().isEmpty()) {
// use internal storage path
} Type guard
boolean hasExternalStorage(File[] extDirs) {
return extDirs != null && extDirs.length > 0 && Arrays.stream(extDirs).anyMatch(Objects::nonNull);
} Try / catch
try {
dir = FileUtils.getBestExternalDataSubdir(extDirs);
} catch (FileNotFoundException e) {
dir = context.getCacheDir();
} Prevention
- Check Environment.getExternalStorageState() before touching external storage
- Always pair external-storage use with an internal-storage fallback
- Avoid storage calls before boot completes
When it happens
Trigger: Calling getExternalCachePath/getBestExternalDataSubdir on a device where Context#getExternalFilesDirs(String, String) returns null — typically because no external/shared volume is mounted or accessible to the app (rare on modern Android; occurs with inaccessible storage profiles, restricted storage permissions, or unusual builds).
Common situations: Devices with emulated storage removed or unmounted; work-profile/secondary-user setups where external dirs are disabled; custom ROMs or emulators with broken storage emulation; running very early in the boot cycle before volumes are scanned.
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
- No available shared storage found.
- Couldn't find any writable Obb dir
- Could not get backup files.
- not found at
- Could not get metadata file.
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/10691666622316dc.
Report an issue: GitHub.