quarkusio/quarkus · error · CodeGenException

Failed to copy file: ${artifactPath} to ${exe}

Error message

Failed to copy file: ${artifactPath} to ${exe}

What it means

After locating the protoc/protoc-gen-grpc-java artifact, Quarkus copies it from the local repository into the build directory as the executable. This CodeGenException wraps an IOException from Files.copy, meaning the JAR could not be copied (unreadable source or unwritable/occupied target path).

Source

Thrown at extensions/grpc/codegen/src/main/java/io/quarkus/grpc/codegen/GrpcCodeGen.java:519

    }

    private Path makeExecutableFromPath(Path buildDir, String groupId, String artifactId, String classifier, String packaging,
            Path artifactPath) throws CodeGenException {
        Path exe = buildDir.resolve(String.format("%s-%s-%s-%s", groupId, artifactId, classifier, packaging));

        if (Files.exists(exe)) {
            return exe;
        }

        if (artifactPath == null) {
            String location = String.format("%s:%s:%s:%s", groupId, artifactId, classifier, packaging);
            throw new CodeGenException("Failed to find " + location + " among dependencies");
        }

        try {
            Files.copy(artifactPath, exe, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            throw new CodeGenException("Failed to copy file: " + artifactPath + " to " + exe, e);
        }
        if (!exe.toFile().setExecutable(true)) {
            throw new CodeGenException("Failed to make the file executable: " + exe);
        }
        return exe;
    }

    private static Path findArtifactPath(ApplicationModel model, String groupId, String artifactId, String classifier,
            String packaging) {
        Path artifactPath = null;

        for (ResolvedDependency artifact : model.getDependencies()) {
            if (groupId.equals(artifact.getGroupId())
                    && artifactId.equals(artifact.getArtifactId())
                    && classifier.equals(artifact.getClassifier())
                    && packaging.equals(artifact.getType())) {
                artifactPath = artifact.getResolvedPaths().getSinglePath();
            }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Run mvn clean / gradle clean and rebuild to remove the conflicting path in target
  2. Check permissions on both the artifact in ~/.m2 (or Gradle cache) and the build output directory
  3. Re-download the artifact if the cached copy is corrupt or partially downloaded
  4. On Windows, exclude target/ from antivirus real-time scanning and stop processes holding the file

Example fix

// before: stale path occupying the exe location
ls target/ # com.google.protobuf-protoc-linux-x86_64-exe is a directory
// after
cd . && mvn clean compile
Defensive patterns

Strategy: validation

Validate before calling

Path exe = buildDir.resolve("com.google.protobuf-protoc-" + classifier + "-exe");
if (Files.exists(exe) && !Files.isRegularFile(exe)) {
    throw new IllegalStateException(exe + " exists but is not a regular file; run mvn clean");
}

Try / catch

try {
    build.run();
} catch (CodeGenException e) {
    if (e.getMessage().startsWith("Failed to copy file:")) {
        exec("mvn clean"); // then retry the build once
        build.run();
    }
}

Prevention

When it happens

Trigger: Code generation where buildDir/<groupId>-<artifactId>-<classifier>-<packaging> cannot be written — target path exists as a directory, parent dir is read-only, or source artifact path is unreadable/locked.

Common situations: Stale build dirs where a directory replaced the expected file; Maven repo cache partially downloaded; Windows file locking by antivirus or a previous crashed build; read-only container filesystems.

Related errors


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