{"record":{"id":"ab660369af404932","repo":"MuntashirAkon/AppManager","slug":"external-directory-containing-datasource-is-not-mounted","errorCode":null,"errorMessage":"External directory containing ${dataSource} is not mounted.","messagePattern":"External directory containing (.+?) is not mounted\\.","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/RestoreOp.java","lineNumber":566,"sourceCode":"                    }\n                    break;\n                case BackupDataDirectoryInfo.TYPE_CREDENTIAL_PROTECTED:\n                case BackupDataDirectoryInfo.TYPE_CUSTOM:\n                case BackupDataDirectoryInfo.TYPE_DEVICE_PROTECTED:\n                    // NOP\n                    break;\n            }\n        } else {\n            // Skip if internal data restore is not requested.\n            if (!mRequestedFlags.backupInternalData()) {\n                return;\n            }\n        }\n        // Create data folder if not exists\n        if (!dataSourceFile.exists()) {\n            if (dataDirectoryInfo.isExternal() && !dataDirectoryInfo.isMounted) {\n                if (!Utils.isRoboUnitTest()) {\n                    throw new BackupException(\"External directory containing \" + dataSource + \" is not mounted.\");\n                } // else Skip checking for mounted partition for robolectric tests\n            }\n            if (!dataSourceFile.mkdirs()) {\n                throw new BackupException(\"Could not create directory \" + dataSourceFile);\n            }\n            if (!dataDirectoryInfo.isExternal()) {\n                // Restore UID, GID\n                dataSourceFile.setUidGid(uidGidPair);\n            }\n        }\n        // Decrypt data\n        try {\n            dataFiles = mBackupItem.decrypt(dataFiles);\n        } catch (IOException e) {\n            throw new BackupException(\"Failed to decrypt \" + Arrays.toString(dataFiles), e);\n        }\n        // Extract data to the data directory\n        try {","sourceCodeStart":548,"sourceCodeEnd":584,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/RestoreOp.java#L548-L584","documentation":"When the target data directory does not exist and it lives on external storage (e.g. /sdcard/Android/data/...), restoreDirectory refuses to create it if dataDirectoryInfo.isMounted reports the external volume is not mounted. Thrown only outside Robolectric tests, where the mount check is skipped. Creating folders on an unmounted volume would silently write to a fake FUSE path, so this is a guard.","triggerScenarios":"Restoring data that includes external-storage directories while the SD card/portable storage is unmounted; USB-OTG storage disconnected; adoptable storage not decrypted after reboot; emulated external storage not yet available at restore time.","commonSituations":"Restoring to a device whose SD card was removed; restoring before user unlocks/decrypts adoptable storage; automation running restore very early after boot.","solutions":["Mount/remount the external storage (re-insert the SD card) and rerun the restore.","Check Settings > Storage to confirm the volume is mounted and accessible.","For adoptable storage, unlock the device so encrypted storage mounts before restoring.","Move the backup data to internal storage or restore only internal data dirs."],"exampleFix":"// before: restore with SD card removed\new RestoreOp(...).runRestore(); // throws: not mounted\n// after: precondition check in caller\nif (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {\n    promptUserToMountSdCard(); // then retry restore\n}\nrunRestore();","handlingStrategy":"validation","validationCode":"String state = Environment.getExternalStorageState();\nif (!Environment.MEDIA_MOUNTED.equals(state))\n    throw new IllegalStateException(\"External storage must be mounted before restore\");\n","typeGuard":"boolean isStorageReady(BackupDataDirectoryInfo info) { return !info.isExternal || info.isMounted; }","tryCatchPattern":"try { runRestore(); } catch (BackupException e) {\n    if (e.getMessage().contains(\"is not mounted\")) {\n        requestStorageMount(); // reinsert SD card / unlock adoptable storage, then retry\n    } else throw e;\n}","preventionTips":["Reinsert/mount SD cards before restoring external data.","Unlock the device so adoptable storage mounts.","Delay automated restores until after boot completes (BOOT_COMPLETED + storage ready).","Prefer internal-storage backups for unattended restores."],"tags":["android","backup","external-storage","storage-mounted"],"backgroundTag":"directory-not-found","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"}