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

  1. Check the configured targetDirectory path is valid and its parent is writable
  2. Remove any file that occupies a segment of the path
  3. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/62edaea078a60145. Report an issue: GitHub.