MuntashirAkon/AppManager · error · IOException

Directory cannot be converted to file

Error message

Directory cannot be converted to file

What it means

During findOrCreateFile(), if an existing child matches the display name but is a directory, the method throws IOException("Directory cannot be converted to file"). The library will not delete or overwrite a directory to satisfy a file creation. The name is already occupied by a directory.

Solutions

  1. Check hasFile(name) and whether the existing entry isDirectory() first; choose a different filename or migrate the data.
  2. Delete the directory (after confirming it is safe/empty) before creating the file.
  3. Rename the existing directory, then create the file.
  4. Version your names (e.g. "cache-v2") to avoid collisions across app upgrades.

Example fix

// before
path.findOrCreateFile("cache", mime); // IOException: Directory cannot be converted to file
// after
if (path.hasFile("cache") && path.findFile("cache").isDirectory()) {
    path.findFile("cache").delete(); // after verifying it is safe
}
path.findOrCreateFile("cache", mime);
Defensive patterns

Strategy: validation

Validate before calling

if (path.hasFile(name)) {
    Path existing = path.findFile(name);
    if (existing.isDirectory()) { /* rename, delete, or pick a new name */ }
}

Type guard

boolean isFileCandidate(Path p, String n) { try { return !p.hasFile(n) || !p.findFile(n).isDirectory(); } catch (FileNotFoundException e) { return true; } }

Try / catch

try { path.findOrCreateFile(name, mime); } catch (IOException e) { if ("Directory cannot be converted to file".equals(e.getMessage())) { /* choose alternate name or migrate */ } }

Prevention

When it happens

Trigger: Calling findOrCreateFile("name", mime) when a directory named "name" already exists under the target directory (found via documentFile.findFile).

Common situations: App version change where a formerly-directory location is now used as a file (e.g. "cache" as dir then as file); user-created folder with the same name as a planned file; restoring backups that map dirs onto file names.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/9475ba9077cf188c. Report an issue: GitHub.

Appendix: source

Thrown at app/src/main/java/io/github/muntashirakon/io/PathImpl.java:499

            throw new IOException("Empty display name.");
        }
        if (displayName.indexOf(File.separatorChar) != -1) {
            throw new IllegalArgumentException("Display name contains file separator.");
        }
        DocumentFile documentFile = getRealDocumentFile(this.documentFile);
        if (!documentFile.isDirectory()) {
            throw new IOException("Current file is not a directory.");
        }
        String extension = null;
        if (mimeType != null) {
            extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
        } else mimeType = DEFAULT_MIME;
        String nameWithExtension = displayName + (extension != null ? "." + extension : "");
        checkVfs(Paths.appendPathSegment(documentFile.getUri(), nameWithExtension));
        DocumentFile file = documentFile.findFile(displayName);
        if (file != null) {
            if (file.isDirectory()) {
                throw new IOException("Directory cannot be converted to file");
            }
            return new PathImpl(context, file);
        }
        file = documentFile.createFile(mimeType, displayName);
        if (file == null) {
            throw new IOException("Could not create " + documentFile.getUri() + File.separatorChar + nameWithExtension + " with type " + mimeType);
        }
        return new PathImpl(context, file);
    }

    @NonNull
    public Path findOrCreateDirectory(@NonNull String displayName) throws IOException {
        displayName = Paths.sanitize(displayName, true);
        if (displayName == null) {
            throw new IOException("Empty display name.");
        }
        if (displayName.indexOf(File.separatorChar) != -1) {
            throw new IllegalArgumentException("Display name contains file separator.");

View on GitHub (pinned to 0152f468fc)