MuntashirAkon/AppManager · error · IOException
Destination is a mount point.
Error message
Destination is a mount point.
What it means
Thrown by PathImpl.checkVfs when a copy/move destination resolves to an active VirtualFileSystem mount point in this library. Mount points are special nodes backed by a mounted filesystem (APK/DEX), so writing through them would corrupt or shadow the mount. The operation is aborted with a plain IOException.
Solutions
- Choose a destination path that is not a mount point (write next to it, not onto it).
- Unmount the filesystem at the destination first with VirtualFileSystem.unmount(mountPoint) (or its Uri-based API), then retry the operation.
- If replacing a mount is intended, use the remount option/flag instead of a plain mount/copy.
- Before the operation, check VirtualFileSystem.getFileSystem(destUri) != null and route accordingly.
Example fix
// before
newPath.copy(destinationMountPoint, StandardCopyOption.REPLACE_EXISTING);
// after
if (VirtualFileSystem.getFileSystem(destinationMountPoint.getUri()) != null) {
VirtualFileSystem.unmount(destinationMountPoint.getUri());
}
newPath.copy(destinationMountPoint, StandardCopyOption.REPLACE_EXISTING); Defensive patterns
Strategy: validation
Validate before calling
if (VirtualFileSystem.getFileSystem(destUri) != null) {
throw new IllegalArgumentException("Destination is a mount point: " + destUri);
} Try / catch
try {
src.copy(dest);
} catch (IOException e) {
if ("Destination is a mount point.".equals(e.getMessage())) {
VirtualFileSystem.unmount(dest.getUri());
src.copy(dest);
} else throw e;
} Prevention
- Check VirtualFileSystem.getFileSystem() on any user-chosen destination before writing.
- Maintain a registry of active mount points in app UI so users can't pick them as destinations.
- Unmount mounts deterministically when the feature using them closes.
When it happens
Trigger: Calling Path copy/move (or any PathImpl API that calls checkVfs) with a destination Uri for which VirtualFileSystem.getFileSystem(uri) != null, i.e. the Uri is currently registered as a mount point; performing the operation without unmounting first.
Common situations: Users of IO/PathUtils try to extract or overwrite files directly onto a mounted APK/DEX mount point (e.g. copying a file onto /mnt/apk/... style path); remount flows that forgot the remount flag; stale mounts left over from a previous session.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Mount point ( ) is already in use.
- already exists.
- Cannot find
- Class definition for + node.getFullPath() + is not found.
- Class definition for + src.getFullPath() + is not found.
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/615288b6cdf69467.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/io/github/muntashirakon/io/PathImpl.java:1381
return documentFile;
}
@Nullable
private static DocumentFile resolveFileOrNull(@NonNull DocumentFile documentFile) {
DocumentFile realDocumentFile = getRealDocumentFile(documentFile);
if (!realDocumentFile.isDirectory()) {
return realDocumentFile;
}
// Try original
if (!documentFile.isDirectory()) {
return documentFile;
}
return null;
}
private static void checkVfs(Uri uri) throws IOException {
if (VirtualFileSystem.getFileSystem(uri) != null) {
throw new IOException("Destination is a mount point.");
}
}
private static boolean isDocumentsProvider(@NonNull Context context, @Nullable String authority) {
final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
final List<ResolveInfo> infos = context.getPackageManager().queryIntentContentProviders(intent, 0);
for (ResolveInfo info : infos) {
if (Objects.equals(authority, info.providerInfo.authority)) {
return true;
}
}
return false;
}
private static class ProxyStorageCallback extends StorageManagerCompat.ProxyFileDescriptorCallbackCompat {
@NonNull
private final FileChannel mChannel;
View on GitHub (pinned to 0152f468fc)