SonarSource/sonarqube · error · IOException
Directory could not be created
Error message
Directory could not be created
What it means
In Files2.openOutputStreamOrThrowIOE, before opening a FileOutputStream for a non-existent file, the code creates the parent directory with mkdirs(). If mkdirs() fails and the parent is still not a directory, it throws an IOException "Directory <parent> could not be created", which openOutputStream then wraps in an IllegalStateException. It signals the output file's parent directory could not be created.
Source
Thrown at server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/util/Files2.java:152
* The parent directory will be created if it does not exist.
* The file will be created if it does not exist.
*
* @param file the file to open for output, must not be {@code null}
* @param append if {@code true}, then bytes will be added to the
* end of the file rather than overwriting
* @return a new {@link FileOutputStream} for the specified file
* @throws IOException if the specified file is a directory
* @throws IOException if the file can not be written to
* @throws IOException if a parent directory can not be created
*/
public FileOutputStream openOutputStreamOrThrowIOE(File file, boolean append) throws IOException {
if (file.exists()) {
checkOrThrowIOE(!file.isDirectory(), "File %s exists but is a directory", file);
checkOrThrowIOE(file.canWrite(), "File %s can not be written to", file);
} else {
File parent = file.getParentFile();
if (parent != null && !parent.mkdirs() && !parent.isDirectory()) {
throw new IOException("Directory " + parent + " could not be created");
}
}
return new FileOutputStream(file, append);
}
/**
* Opens a {@link FileOutputStream} for the specified file, checking and
* creating the parent directory if it does not exist.
* <p>
* The parent directory will be created if it does not exist.
* The file will be created if it does not exist.
*
* @param file the file to open for output, must not be {@code null}
* @param append if {@code true}, then bytes will be added to the
* end of the file rather than overwriting
* @return a new {@link FileOutputStream} for the specified file
* @throws IllegalStateException if the specified file is a directory
* @throws IllegalStateException if the file can not be written toView on GitHub (pinned to 184c821202)
Solutions
- Check that every path component of the parent is a directory, not a file, and remove any conflicting file
- Grant the CE process user write/execute permission on all ancestor directories
- Verify the configured paths (sonar.path.data / temp dirs) are valid and on a writable volume
- Create the parent directory manually and re-run the task
Example fix
// before
files2.openOutputStream(new File("/opt/sonar/work")); // 'work' is a regular file -> mkdirs fails
// after
File target = new File("/opt/sonar/work/out.bin");
File parent = target.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
throw new IOException("Pre-check failed for " + parent);
}
files2.openOutputStream(target); Defensive patterns
Strategy: validation
Validate before calling
File parent = file.getParentFile();
if (parent != null && parent.exists() && !parent.isDirectory()) {
throw new IllegalStateException("Path component is a file: " + parent);
}
if (parent != null && !parent.canWrite()) {
throw new IllegalStateException("Parent not writable: " + parent);
} Try / catch
try {
FileOutputStream out = files2.openOutputStream(file, false);
} catch (IllegalStateException e) {
LOGGER.error("Cannot create parent dir for {}: {}", file, e.getCause(), e);
} Prevention
- Make sure configured work/temp paths point to directories, not files
- Grant the CE user write access to all parent directories
- Pre-create directory trees during installation
- Avoid overly long or OS-invalid paths
When it happens
Trigger: The target file does not exist, its parent directory also does not exist, and File.mkdirs() returns false without creating it — e.g. a path component is an existing file, permission denied on an ancestor, or invalid path characters.
Common situations: Configured work/temp directory path collides with an existing regular file; CE user lacks write permission on the parent; path too long or containing invalid characters; read-only volume.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- Can not delete
- Can not move file to
- Can not open file
- Can not write to file
- Can not unzip file ${zipFile} to directory ${toDir}
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/9eab92a54270c5c9.
Report an issue: GitHub.