maotoumao/MusicFree · warning
toast.folderNotExistOrNoPermission
Error message
toast.folderNotExistOrNoPermission
What it means
Warning toast in the download-path picker's onAction callback (basicSetting.tsx:366). After the user selects a folder, the code calls readdir(targetDir.path) to validate it is actually readable; if that promise rejects, the folder is treated as non-existent or permission-denied and the selection is rejected (returns false) without saving basic.downloadPath.
Source
Thrown at src/pages/setting/settingTypes/basicSetting.tsx:366
pathConst.downloadMusicPath}
</ThemeText>
),
onPress() {
navigate<"file-selector">(ROUTE_PATH.FILE_SELECTOR, {
fileType: "folder",
multi: false,
actionText: t("basicSettings.fileSelector.selectFolder"),
async onAction(selectedFiles) {
try {
const targetDir = selectedFiles[0];
await readdir(targetDir.path);
Config.setConfig(
"basic.downloadPath",
targetDir.path,
);
return true;
} catch {
Toast.warn(t("toast.folderNotExistOrNoPermission"));
return false;
}
},
});
},
},
createRadio(
t("basicSettings.maxDownload"),
"basic.maxDownload",
[1, 3, 5, 7],
maxDownload ?? 3,
),
createRadio(
t("basicSettings.defaultDownloadQuality"),
"basic.defaultDownloadQuality",
qualityKeys,
defaultDownloadQuality ?? "standard",
{
View on GitHub (pinned to d118b18b3d)
Solutions
- Grant the app storage permission (Settings > Apps > MusicFree > Permissions, or All files access on Android 11+)
- Verify the folder exists and storage is mounted (re-plug/remount SD card), then pick it again
- Choose a folder in app-accessible storage (e.g. /storage/emulated/0/Music) instead of a restricted/rooted path
- Restart the app to refresh SAF permission grants, then retry the selection
Example fix
// before
try {
const targetDir = selectedFiles[0];
await readdir(targetDir.path);
Config.setConfig("basic.downloadPath", targetDir.path);
return true;
} catch {
Toast.warn(t("toast.folderNotExistOrNoPermission"));
return false;
}
// after
try {
const targetDir = selectedFiles[0];
await mkdir(targetDir.path); // no-op if it exists, creates if missing
await readdir(targetDir.path);
Config.setConfig("basic.downloadPath", targetDir.path);
return true;
} catch (e: any) {
Toast.warn(e?.code === "EACCES"
? t("toast.noStoragePermission")
: t("toast.folderNotExistOrNoPermission"));
return false;
} Defensive patterns
Strategy: try-catch
Validate before calling
import { PermissionsAndroid } from "react-native";
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
);
if (granted !== PermissionsAndroid.RESULTS.GRANTED) return false;
await readdir(targetDir.path); // fails -> folder missing or no permission Try / catch
try {
await readdir(targetDir.path);
Config.setConfig("basic.downloadPath", targetDir.path);
return true;
} catch {
Toast.warn(t("toast.folderNotExistOrNoPermission"));
return false;
} Prevention
- Grant storage/All-files-access permission before picking a download folder
- Avoid picking folders on removable or recently unmounted storage
- Prefer app-accessible directories (e.g. /storage/emulated/0/Music)
- Re-select the folder after app updates that reset permission grants
When it happens
Trigger: readdir() on the chosen path throws because the directory was deleted/moved between selection and validation, it sits on unmounted storage (SD card, USB OTG), or Android storage permissions (READ/WRITE_EXTERNAL_STORAGE or SAF grants) are missing for that location.
Common situations: Selecting a folder on a removable SD card that was unmounted; picking a path under /storage/emulated/0 without storage permission granted in Android settings; directory removed by another app or a file manager after selection; app not granted 'All files access' for restricted paths.
Related errors
AI-assisted analysis of maotoumao/MusicFree@d118b18b3d (2026-08-30).
Data as JSON: /api/errors/8d90fbcbd59bbc96.
Report an issue: GitHub.