{"record":{"id":"f655771f7140d86e","repo":"MuntashirAkon/AppManager","slug":"target-is-not-backed-by-a-real-file","errorCode":null,"errorMessage":"Target is not backed by a real file","messagePattern":"Target is not backed by a real file","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/io/PathImpl.java","lineNumber":1269,"sourceCode":"    public FileChannel openFileChannel(int mode) throws IOException {\n        DocumentFile documentFile = resolveFileOrNull(this.documentFile);\n        if (documentFile == null) {\n            throw new IOException(this.documentFile.getUri() + \" is a directory\");\n        }\n        if (documentFile instanceof ExtendedRawDocumentFile) {\n            ExtendedFile file = Objects.requireNonNull(getFile());\n            if (file instanceof RemoteFile) {\n                try {\n                    return LocalServices.getFileSystemManager().openChannel(file, mode);\n                } catch (RemoteException e) {\n                    throw new IOException(e);\n                }\n            }\n            return FileSystemManager.getLocal().openChannel(file, mode);\n        } else if (documentFile instanceof VirtualDocumentFile) {\n            return ((VirtualDocumentFile) documentFile).openChannel(mode);\n        }\n        throw new IOException(\"Target is not backed by a real file\");\n    }\n\n    @NonNull\n    private static Path createFileAsDirectChild(@NonNull Context context,\n                                                @NonNull DocumentFile documentFile,\n                                                @NonNull String displayName,\n                                                @Nullable String mimeType) throws IOException {\n        if (displayName.indexOf(File.separatorChar) != -1) {\n            throw new IllegalArgumentException(\"Display name contains file separator.\");\n        }\n        documentFile = getRealDocumentFile(documentFile);\n        if (!documentFile.isDirectory()) {\n            throw new IOException(\"Current file is not a directory.\");\n        }\n        String extension = null;\n        if (mimeType != null) {\n            extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);\n        } else mimeType = DEFAULT_MIME;","sourceCodeStart":1251,"sourceCodeEnd":1287,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/io/PathImpl.java#L1251-L1287","documentation":"Thrown by PathImpl.openFileChannel() when the resolved DocumentFile is neither an ExtendedRawDocumentFile nor a VirtualDocumentFile — i.e. a generic SAF document with no real backing file accessible to the process. FileChannel semantics require a real file descriptor, which SAF-only documents cannot provide.","triggerScenarios":"Calling Path.openFileChannel(mode) on a standard content:// document URI (external storage via DocumentsProvider, cloud providers, DownloadsProvider) rather than a raw/virtual-backed path.","commonSituations":"Files on removable SD card accessed via SAF; documents in Download folder exposed only through DocumentsProvider; cloud-storage documents (Drive) with no local file; trying to use FileChannel-based APIs (mmap, RandomAccessFile-like access) on SAF-only content.","solutions":["Use Path.openInputStream()/openOutputStream() instead of openFileChannel for SAF documents","Check the backing type before choosing the channel API","Move files to app-private storage and open a channel there when channel semantics are required","Handle this IOException with a fallback to stream-based copy"],"exampleFix":"// before\nFileChannel ch = path.openFileChannel(PathUtils.MODE_READ);\n// after\nFileChannel ch;\ntry {\n    ch = path.openFileChannel(PathUtils.MODE_READ);\n} catch (IOException e) {\n    try (InputStream in = path.openInputStream()) {\n        File tmp = File.createTempFile(\"vfs\", null, context.getCacheDir());\n        Files.copy(in, tmp.toPath(), StandardCopyOption.REPLACE_EXISTING);\n        ch = FileChannel.open(tmp.toPath(), StandardOpenOption.READ);\n    }\n}","handlingStrategy":"fallback","validationCode":"boolean backed = path.getUri().getScheme().equals(\"file\") || path instanceof RawPath; // choose streams otherwise","typeGuard":"null","tryCatchPattern":"try { return path.openFileChannel(mode); } catch (IOException e) { return copyToCacheAndOpenChannel(path); }","preventionTips":["Prefer stream APIs for SAF content URIs","Reserve openFileChannel for raw/local-file backed paths","Document in your code which URI schemes support channels"],"tags":["io","android","saf","filechannel"],"backgroundTag":"operation-not-supported","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}