{"record":{"id":"1da0062c88b21f52","repo":"MuntashirAkon/AppManager","slug":"data-directory-cannot-be-empty","errorCode":null,"errorMessage":"Data directory cannot be empty.","messagePattern":"Data directory cannot be empty\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/BackupUtils.java","lineNumber":331,"sourceCode":"        // Lib dirs has to be ignored by default\n        List<String> excludeDirs = new ArrayList<>(Arrays.asList(BackupManager.LIB_DIR));\n        if (includeCache) {\n            excludeDirs.addAll(Arrays.asList(BackupManager.CACHE_DIRS));\n        }\n        if (others != null) {\n            excludeDirs.addAll(Arrays.asList(others));\n        }\n        return excludeDirs.toArray(new String[0]);\n    }\n\n    @SuppressLint(\"SdCardPath\")\n    @NonNull\n    static List<String> getDataDirectories(@NonNull ApplicationInfo applicationInfo, boolean loadInternal,\n                                       boolean loadExternal, boolean loadMediaObb) {\n        // Data directories *must* be readable and non-empty\n        ArrayList<String> dataDirs = new ArrayList<>();\n        if (applicationInfo.dataDir == null) {\n            throw new IllegalArgumentException(\"Data directory cannot be empty.\");\n        }\n        int userId = UserHandleHidden.getUserId(applicationInfo.uid);\n        if (loadInternal) {\n            String dataDir = applicationInfo.dataDir;\n            if (dataDir.startsWith(\"/data/data/\")) {\n                dataDir = Utils.replaceOnce(dataDir, \"/data/data/\", String.format(Locale.ROOT, \"/data/user/%d/\", userId));\n            }\n            dataDirs.add(dataDir);\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && applicationInfo.deviceProtectedDataDir != null) {\n                // /data/user_de/{userId}\n                dataDirs.add(applicationInfo.deviceProtectedDataDir);\n            }\n        }\n        // External directories could be /sdcard, /storage/sdcard, /storage/emulated/{userId}\n        OsEnvironment.UserEnvironment ue = OsEnvironment.getUserEnvironment(userId);\n        if (loadExternal) {\n            Path[] externalFiles = ue.buildExternalStorageAppDataDirs(applicationInfo.packageName);\n            for (Path externalFile : externalFiles) {","sourceCodeStart":313,"sourceCodeEnd":349,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/BackupUtils.java#L313-L349","documentation":"getDataDirectories collects the data directories of an application for backup. It documents that data directories must be readable and non-empty, so if ApplicationInfo.dataDir is null the method immediately throws IllegalArgumentException because no backup of app data is possible without a data directory path.","triggerScenarios":"Calling getDataDirectories with an ApplicationInfo whose dataDir field is null — typically for system/shared apps or applications not installed for the queried user.","commonSituations":"Backing up an app whose ApplicationInfo was obtained for a user where it is not installed, or from a stale/removed package record; also happens with disabled or hidden system packages on some OEM ROMs.","solutions":["Check applicationInfo.dataDir != null before calling getDataDirectories and skip/flag that app for backup.","Re-resolve ApplicationInfo for the correct user via PackageManager with the matching user handle.","Verify the package is actually installed and enabled for the target user before scheduling backup."],"exampleFix":"// before\nList<String> dirs = BackupUtils.getDataDirectories(appInfo, true, true, true);\n// after\nif (appInfo.dataDir == null) {\n    throw new BackupException(appInfo.packageName + \" is not installed for this user; skipping backup\");\n}\nList<String> dirs = BackupUtils.getDataDirectories(appInfo, true, true, true);","handlingStrategy":"validation","validationCode":"if (applicationInfo == null || applicationInfo.dataDir == null) {\n    // skip or re-resolve ApplicationInfo for the correct user\n    return Collections.emptyList();\n}","typeGuard":"boolean isBackable(ApplicationInfo info) { return info != null && info.dataDir != null; }","tryCatchPattern":null,"preventionTips":["Always resolve ApplicationInfo for the exact user handle being backed up.","Filter out packages not installed/enabled for the target user before backup.","Unit-test backup flows with system and disabled packages."],"tags":["android","backup","illegal-argument","null-pointer"],"backgroundTag":"null-argument","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}