quarkusio/quarkus · error · MojoExecutionException
Unable to create directory: ${directory}
Error message
Unable to create directory: ${directory} What it means
initTargetDirectory creates the plugin's output directory with Files.createDirectories and converts an IOException into a MojoExecutionException naming the directory. The build stops because documentation cannot be written without it.
Source
Thrown at devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/GenerateConfigDocMojo.java:270
private static String generateAllConfig(Engine quteEngine, Context context,
Map<Extension, Map<ConfigRootKey, ConfigRoot>> configRootsByExtensions) {
return quteEngine.getTemplate("allConfig")
.data("configRootsByExtensions", configRootsByExtensions)
.data("searchable", true)
.data("context", context)
.data("summaryTableId", context.summaryTableId()) // for backward compatibility, use context instead
.data("additionalAnchorPrefix", "")
.data("includeDurationNote", true)
.data("includeMemorySizeNote", true)
.render();
}
private static void initTargetDirectory(Path resolvedTargetDirectory) throws MojoExecutionException {
try {
Files.createDirectories(resolvedTargetDirectory);
} catch (IOException e) {
throw new MojoExecutionException("Unable to create directory: " + resolvedTargetDirectory, e);
}
}
static List<Path> findTargetDirectories(Path scanDirectory) throws MojoExecutionException {
try {
List<Path> targets = new ArrayList<>();
Files.walkFileTree(scanDirectory, new SimpleFileVisitor<>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
if (dir.endsWith(TARGET)) {
// we check if there is a POM around as it might happen that the target/ directory is still around
// while the module has been dropped
if (Files.exists(dir.resolve("../pom.xml"))) {
targets.add(dir);
}
View on GitHub (pinned to e1c734241f)
Solutions
- Check the configured targetDirectory path is valid and its parent is writable
- Remove any file that occupies a segment of the path
- Run the build in a writable location (e.g. under target/) instead of a read-only mount
Example fix
// before
<targetDirectory>/opt/docs</targetDirectory> <!-- read-only mount -->
// after
<targetDirectory>${project.build.directory}/generated-docs</targetDirectory> Defensive patterns
Strategy: validation
Validate before calling
Path dir = Paths.get(targetDirectory);
Path parent = dir.toAbsolutePath().getParent();
if (parent == null || !Files.isWritable(parent)) {
throw new IllegalStateException("Cannot create dir: " + dir);
}
if (Files.exists(dir) && !Files.isDirectory(dir)) {
throw new IllegalStateException("Path is a file: " + dir);
} Try / catch
try {
mojo.execute();
} catch (MojoExecutionException e) {
if (e.getMessage().startsWith("Unable to create directory")) {
// check permissions / path before retrying
}
} Prevention
- Default to ${project.build.directory}/... paths
- Never point output at read-only mounts
- Verify CI containers run as a user with write access
When it happens
Trigger: generateConfigDoc runs with a targetDirectory that cannot be created: parent path is a file, permissions deny write, path is invalid on the filesystem, or disk is full.
Common situations: Absolute paths from Windows-style config on Linux CI; read-only Docker build containers; a file already occupies a path segment of the directory.
Related errors
- Unable to collect the target directories
- Could not create directory ${outputDirectory}
- Could not create directory ${outputDirectory}
- Failed to create <classesDir>
- Failed to create the output dir ${projectFile}
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/62edaea078a60145.
Report an issue: GitHub.