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
- Ensure the target directory (resolvedTargetDirectory) exists and is writable before running the goal.
- Check that no directory occupies the file path the plugin wants to write (e.g. <artifactId>.<ext>).
- 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
- Pre-create and chmod the target directory in CI pipelines.
- Ensure nothing occupies the extension-named file path as a directory.
- Check disk space on the target volume.
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
- Unable to render config roots for top level prefix: ${topLev
- Unable to render config roots for specific file: ${fileName}
- Failed to copy %s to %s
- Failed to scan extensions directory: ${extRoot}
- Failed to persist extension descriptor ${output.resolve(Boot
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/401e812843242f6b.
Report an issue: GitHub.