asLody/VirtualApp · error · IOException

Couldn't create directory

Error message

Couldn't create directory 

What it means

AtomicFile.startWrite opens the base file for writing; on FileNotFoundException it attempts parent.mkdir() to recreate a missing directory. If that mkdir fails it throws this IOException including the file path. It protects atomic-write users from silently writing into a nonexistent directory.

Solutions

  1. Ensure the parent directory exists before creating AtomicFile, using mkdirs() on the full chain and checking writable state
  2. Verify storage is mounted (Environment.getExternalStorageState) and path is app-writable
  3. Log/inspect the exact path; fix the path construction to live under context.getFilesDir()/getCacheDir()

Example fix

// before
AtomicFile af = new AtomicFile(new File("/data/system/users/0/x.xml"));
// after
File dir = new File("/data/system/users/0");
if (!dir.exists() && !dir.mkdirs()) {
    throw new IOException("cannot create " + dir);
}
AtomicFile af = new AtomicFile(new File(dir, "x.xml"));
Defensive patterns

Strategy: validation

Validate before calling

File base = new File(dir, "file.xml");
File parent = base.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
    throw new IOException("cannot create " + parent);
}
if (!parent.canWrite()) throw new IOException("not writable: " + parent);

Try / catch

try {
    FileOutputStream out = atomicFile.startWrite();
} catch (IOException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Couldn't create directory")) {
        // recreate directory chain or switch to a writable location
    }
}

Prevention

When it happens

Trigger: Calling AtomicFile.startWrite (directly or via writeUserLocked/writeUserListLocked) when the base file's parent directory does not exist and mkdir() returns false (permission denied, parent-of-parent missing, or storage unmounted).

Common situations: External storage unmounted or read-only; data directory wiped while service still holds an AtomicFile; wrong base path constructed for a restricted user; Android scoped-storage restrictions.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of asLody/VirtualApp@666fefcb5d (2026-09-09). Data as JSON: /api/errors/231aa95bd14dc2f7. Report an issue: GitHub.

Appendix: source

Thrown at VirtualApp/lib/src/main/java/com/lody/virtual/helper/utils/AtomicFile.java:88

    public FileOutputStream startWrite() throws IOException {
        // Rename the current file so it may be used as a backup during the next read
        if (mBaseName.exists()) {
            if (!mBackupName.exists()) {
                if (!mBaseName.renameTo(mBackupName)) {
                    Log.w("AtomicFile", "Couldn't rename file " + mBaseName
                            + " to backup file " + mBackupName);
                }
            } else {
                mBaseName.delete();
            }
        }
        FileOutputStream str = null;
        try {
            str = new FileOutputStream(mBaseName);
        } catch (FileNotFoundException e) {
            File parent = mBaseName.getParentFile();
            if (!parent.mkdir()) {
                throw new IOException("Couldn't create directory " + mBaseName);
            }
            try {
                str = new FileOutputStream(mBaseName);
            } catch (FileNotFoundException e2) {
                throw new IOException("Couldn't create " + mBaseName);
            }
        }
        return str;
    }

    /**
     * Call when you have successfully finished writing to the stream
     * returned by {@link #startWrite()}.  This will close, sync, and
     * commit the new data.  The next attempt to read the atomic file
     * will return the new file stream.
     */
    public void finishWrite(FileOutputStream str) {
        if (str != null) {

View on GitHub (pinned to 666fefcb5d)