MuntashirAkon/AppManager · error · IOException

already exists.

Error message

 already exists.

What it means

createDirectories() checks whether the final segment already exists (via the VFS root or findFile) and throws IOException("<uri> already exists.") if it does. The method only creates directories; it does not tolerate existing entries, unlike a true mkdirs/exists-ok semantic. The message includes the existing entry's URI.

Solutions

  1. Check hasFile(lastSegment) or catch the IOException and treat "already exists" as success if an existing directory is acceptable.
  2. Use findOrCreateDirectory instead of createDirectories when existence is expected.
  3. Delete or rename the conflicting existing entry before creating.
  4. Guard concurrent creators with app-level synchronization or a unique per-run name.

Example fix

// before
path.createDirectories("logs"); // throws on second run
// after
if (!path.hasFile("logs")) {
    path.createDirectories("logs");
} else {
    path.findOrCreateDirectory("logs");
}
Defensive patterns

Strategy: try-catch

Validate before calling

boolean exists = path.hasFile(lastSegment);
if (exists) { /* reuse, rename, or delete first */ }

Try / catch

try {
    return path.createDirectories(name);
} catch (IOException e) {
    if (e.getMessage() != null && e.getMessage().endsWith(" already exists.")) {
        return path.findOrCreateDirectory(name); // tolerate existing
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling createDirectories when the last path segment already exists as any entry (file or directory) at that location, e.g. a second call with the same name, or a file already occupying the name.

Common situations: Re-running an install/setup routine that creates fixed directories; a race where another process created the directory first; a stale file with the intended directory name left from a previous version.

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/01aaf7fe3ddaed57. Report an issue: GitHub.

Appendix: source

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

        if (displayName == null) {
            throw new IOException("Empty display name.");
        }
        String[] dirNames = displayName.split(File.separator);
        if (dirNames.length == 0) {
            throw new IllegalArgumentException("Display name is empty");
        }
        for (String name : dirNames) {
            if (name.equals("..")) {
                throw new IOException("Could not create directories in the parent directory.");
            }
        }
        DocumentFile file = createArbitraryDirectories(documentFile, dirNames, dirNames.length - 1);
        // Special case for the last segment
        String lastSegment = dirNames[dirNames.length - 1];
        Path fsRoot = VirtualFileSystem.getFsRoot(Paths.appendPathSegment(file.getUri(), lastSegment));
        DocumentFile t = fsRoot != null ? fsRoot.documentFile : file.findFile(lastSegment);
        if (t != null) {
            throw new IOException(t.getUri() + " already exists.");
        }
        t = file.createDirectory(lastSegment);
        if (t == null) {
            throw new IOException("Directory" + file.getUri() + File.separator + lastSegment + " could not be created.");
        }
        return new PathImpl(context, t);
    }

    @Nullable
    public Path getParent() {
        DocumentFile file = getRealDocumentFile(documentFile).getParentFile();
        return file == null ? null : new PathImpl(context, file);
    }

    public boolean hasFile(@NonNull String displayName) {
        return findFileInternal(documentFile, displayName) != null;
    }

View on GitHub (pinned to 0152f468fc)