MuntashirAkon/AppManager · error · IOException

Existing file is not a directory

Error message

Existing file is not a directory

What it means

When a child with the requested display name already exists but is a regular file, findOrCreateDirectory() throws IOException("Existing file is not a directory") rather than overwriting or failing at create time. This protects existing file content from being clobbered by a directory-creation request.

Source

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

    @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.");
        }
        DocumentFile documentFile = getRealDocumentFile(this.documentFile);
        if (!documentFile.isDirectory()) {
            throw new IOException("Current file is not a directory.");
        }
        Path fsRoot = VirtualFileSystem.getFsRoot(Paths.appendPathSegment(documentFile.getUri(), displayName));
        if (fsRoot != null) return fsRoot;
        DocumentFile file = documentFile.findFile(displayName);
        if (file != null) {
            if (!file.isDirectory()) {
                throw new IOException("Existing file is not a directory");
            }
            return new PathImpl(context, file);
        }
        file = documentFile.createDirectory(displayName);
        if (file == null) throw new IOException("Could not create directory named " + displayName);
        return new PathImpl(context, file);
    }

    @NonNull
    public PathAttributes getAttributes() throws IOException {
        if (documentFile instanceof ExtendedRawDocumentFile) {
            return PathAttributesImpl.fromFile((ExtendedRawDocumentFile) documentFile);
        }
        if (documentFile instanceof VirtualDocumentFile) {
            return PathAttributesImpl.fromVirtual((VirtualDocumentFile) documentFile);
        }
        return PathAttributesImpl.fromSaf(context, documentFile);
    }

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Check documentFile.findFile(name) first; if it exists and is a file, choose a different name or delete the file deliberately
  2. Use Path.exists()/isDirectory() before attempting creation
  3. Handle the IOException and fall back to an alternative directory name

Example fix

// before
path.findOrCreateDirectory("data"); // may collide with existing file
// after
Path existing = path.findFile("data");
if (existing != null && !existing.isDirectory()) {
    existing.delete(); // deliberate decision
}
path.findOrCreateDirectory("data");
Defensive patterns

Strategy: validation

Validate before calling

Path existing = path.findFile(name);
if (existing != null && !existing.isDirectory()) {
    throw new IllegalStateException("'" + name + "' exists as a file");
}

Try / catch

try {
    path.findOrCreateDirectory(name);
} catch (IOException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Existing file is not a directory")) {
        // choose another name or explicitly remove the file
    } else throw e;
}

Prevention

When it happens

Trigger: documentFile.findFile(displayName) returns an existing non-directory document; i.e. a file with the exact same name as the directory you want already exists in the parent.

Common situations: Name collisions after refactors ("data" used as both a file and a directory name), case-insensitive filesystems matching differently-cased names, or leftover files from a previous run.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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