skylot/jadx · error · JadxRuntimeException

Can't create directory ${dir}

Error message

Can't create directory ${dir}

What it means

Thrown by makeDirs(File) when dir.mkdirs() returns false AND dir.isDirectory() returns false. This means the directory could not be created and does not already exist as a directory. The mkdirs() call fails silently (returns false) on permission denial, a parent path component that is a regular file, or a read-only filesystem. The double-check (!isDirectory) allows the call to succeed if the directory already existed (mkdirs returns false but isDirectory returns true).

Source

Thrown at jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java:148

	public static void makeDirsForFile(Path path) {
		if (path != null) {
			makeDirs(path.toAbsolutePath().getParent().toFile());
		}
	}

	public static void makeDirsForFile(File file) {
		if (file != null) {
			makeDirs(file.getParentFile());
		}
	}

	private static final Object MKDIR_SYNC = new Object();

	public static void makeDirs(@Nullable File dir) {
		if (dir != null) {
			synchronized (MKDIR_SYNC) {
				if (!dir.mkdirs() && !dir.isDirectory()) {
					throw new JadxRuntimeException("Can't create directory " + dir);
				}
			}
		}
	}

	public static void makeDirs(@Nullable Path dir) {
		if (dir != null) {
			makeDirs(dir.toFile());
		}
	}

	public static void deleteFileIfExists(Path filePath) throws IOException {
		Files.deleteIfExists(filePath);
	}

	public static boolean deleteDir(File dir) {
		deleteDir(dir.toPath());
		return true;

View on GitHub (pinned to e738a26571)

Solutions

  1. Check whether a parent component is a file: verify each ancestor with Files.isDirectory.
  2. Verify write permission on the parent: Files.isWritable(dir.getParentFile().toPath()).
  3. Remove or rename a colliding file that occupies the intended directory path.
  4. Check filesystem mount options (read-only) and disk/inode availability.

Example fix

// before
FileUtils.makeDirs(outputDir);

// after
Path parent = outputDir.toPath().getParent();
if (parent != null && Files.exists(parent) && !Files.isDirectory(parent)) {
    throw new IllegalStateException(parent + " is a file, cannot create dir under it");
}
FileUtils.makeDirs(outputDir);
Defensive patterns

Strategy: validation

Validate before calling

public static void validateMkdirTarget(File dir) throws IOException {
    File parent = dir.getParentFile();
    while (parent != null) {
        if (parent.exists() && !parent.isDirectory()) {
            throw new IOException("ancestor is a file, not a directory: " + parent);
        }
        parent = parent.getParentFile();
    }
}

Try / catch

try {
    FileUtils.makeDirs(dir);
} catch (JadxRuntimeException e) {
    // no wrapped cause — check the directory state directly
    if (dir.isDirectory()) return; // benign: already exists
    throw e;
}

Prevention

When it happens

Trigger: Calling makeDirs on a path whose parent component is a regular file (e.g., '/foo/bar' where 'foo' is a file), on a read-only filesystem, where the process lacks write permission on the parent, or where the path name contains illegal characters for the OS. Also when disk/inode exhaustion prevents directory creation.

Common situations: Output directory path collides with an existing file name. Running on a read-only root filesystem in a container. Insufficient permissions on the target directory's parent. Windows path with reserved characters. SELinux denying the operation.

Related errors


AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14). Data as JSON: /api/errors/e392a97e4fe720d4. Report an issue: GitHub.