quarkusio/quarkus · error · MojoExecutionException

Unable to copy extension file for: ${extension}

Error message

Unable to copy extension file for: ${extension}

What it means

GenerateConfigDocMojo copies each rendered config-root file to an extension-named file (EXTENSION_FILE_FORMAT) when there is a single top-level prefix. If Files.copy fails, it wraps the exception in this MojoExecutionException naming the extension. It means the rendered page exists but could not be copied to the target extension file path.

Source

Thrown at devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/GenerateConfigDocMojo.java:148

                try {
                    Files.writeString(configRootPath,
                            generateConfigReference(quteEngine, context, extension, configRoot, "", true));
                } catch (Exception e) {
                    throw new MojoExecutionException("Unable to render config roots for top level prefix: " + topLevelPrefix
                            + " in extension: " + extension, e);
                }
            }

            // if we have only one top level prefix, we copy the generated file to a file named after the extension
            // for simplicity's sake
            if (extensionConfigRootsEntry.getValue().size() == 1 && configRootPath != null) {
                Path extensionPath = resolvedTargetDirectory.resolve(String.format(EXTENSION_FILE_FORMAT,
                        extension.artifactId(), normalizedFormat.getExtension()));

                try {
                    Files.copy(configRootPath, extensionPath, StandardCopyOption.REPLACE_EXISTING);
                } catch (Exception e) {
                    throw new MojoExecutionException("Unable to copy extension file for: " + extension, e);
                }
            }
        }

        // we generate the config roots that are saved in a specific file
        for (Entry<String, ConfigRoot> specificFileConfigRootEntry : mergedModel.getConfigRootsInSpecificFile().entrySet()) {
            String annotationFileName = specificFileConfigRootEntry.getKey();
            ConfigRoot configRoot = specificFileConfigRootEntry.getValue();
            Extension extension = configRoot.getExtension();

            if (configRoot.getNonDeprecatedItems().isEmpty()) {
                continue;
            }

            String normalizedFileName = stripAdocSuffix(annotationFileName);
            String fileName = normalizedFileName + "." + normalizedFormat.getExtension();

            Path configRootPath = resolvedTargetDirectory.resolve(fileName);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure the target directory (resolvedTargetDirectory) exists and is writable before running the goal.
  2. Check that no directory occupies the file path the plugin wants to write (e.g. <artifactId>.<ext>).
  3. Run mvn -e to inspect the wrapped IOException for the exact filesystem reason.

Example fix

// before: target dir never created
mvn quarkus:generate-config-doc
// after
mvn quarkus:generate-config-doc -e   # read cause
mkdir -p target/asciidoc && chmod u+w target/asciidoc
Defensive patterns

Strategy: validation

Validate before calling

Path extensionPath = resolvedTargetDirectory.resolve(String.format(EXTENSION_FILE_FORMAT, extension.artifactId(), format.getExtension()));
if (Files.isDirectory(extensionPath)) throw new IllegalStateException("Path is a directory: " + extensionPath);
Files.createDirectories(resolvedTargetDirectory);

Try / catch

try {
    Files.copy(configRootPath, extensionPath, StandardCopyOption.REPLACE_EXISTING);
} catch (Exception e) {
    throw new MojoExecutionException("Unable to copy extension file for: " + extension, e);
}

Prevention

When it happens

Trigger: Running the generate-config-doc goal when Files.copy(configRootPath, extensionPath, REPLACE_EXISTING) throws — typically because the resolvedTargetDirectory does not exist, is not writable, or extensionPath resolves to a directory.

Common situations: CI checkouts where the docs target directory wasn't created; permission-restricted output directories; a stale directory at the extensionPath location blocking the copy.

Related errors


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