quarkusio/quarkus · error · GrpcCodeGenException

Failed to create directory: " + protoOutputDir

Error message

Failed to create directory: " + protoOutputDir

What it means

Quarkus gRPC code generation walks a dependency artifact's content tree and copies each .proto file into a per-artifact work directory. Before copying, it runs Files.createDirectories(protoOutputDir); if the OS returns an IOException (permission denied, path too long, path is a file, disk full), the code wraps it in this GrpcCodeGenException, which is then rethrown as a CodeGenException that aborts the build's code-gen phase.

Source

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

            Set<String> protoDirectories, ResolvedDependency artifact, Collection<String> filesToInclude,
            Collection<String> filesToExclude, boolean isDependency) throws CodeGenException {

        // Proto files from dependencies are always copied to a work directory with known
        // path prefixes (src/main/proto/, src/test/proto/, proto/) stripped. This ensures
        // consistent --proto_path entries for protoc regardless of whether the artifact
        // resolved to a JAR (archive) or a directory (e.g. workspace project's target/classes).
        Path protoOutputDir = getProtoOutputDir(workDir, artifact);
        try {
            artifact.getContentTree(new PathFilter(filesToInclude, filesToExclude)).walk(
                    pathVisit -> {
                        Path path = pathVisit.getPath();
                        if (Files.isRegularFile(path) && path.getFileName().toString().endsWith(PROTO)) {
                            String strippedPathStr = stripProtoPrefix(pathVisit.getResourceName());
                            try {
                                Files.createDirectories(protoOutputDir);
                                protoDirectories.add(protoOutputDir.toString());
                            } catch (IOException e) {
                                throw new GrpcCodeGenException("Failed to create directory: " + protoOutputDir, e);
                            }
                            Path outPath = protoOutputDir.resolve(strippedPathStr);
                            try {
                                Files.createDirectories(outPath.getParent());
                                if (isDependency) {
                                    copySanitizedProtoFile(artifact, path, outPath);
                                } else {
                                    Files.copy(path, outPath, StandardCopyOption.REPLACE_EXISTING);
                                }
                                protoFiles.add(outPath);
                            } catch (IOException e) {
                                throw new GrpcCodeGenException("Failed to extract proto file" + path + " to target: "
                                        + outPath, e);
                            }
                        }
                    });
        } catch (GrpcCodeGenException e) {
            throw new CodeGenException(e.getMessage(), e);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Check permissions/ownership of the build output directory (e.g. target/) and ensure the build user can write to it
  2. Run mvn clean (or gradle clean) to remove stale conflicting files, then rebuild
  3. Check disk space with df -h; free space if the volume is full
  4. On Windows, shorten the project path or enable long-path support to avoid MAX_PATH issues
  5. If the directory is read-only in CI, add a writable workspace/volume for the build

Example fix

// before: building in a read-only CI checkout
mvn -Dmaven.repo.local=/ro/repo compile
// after: point output to a writable location and clean first
mvn clean compile -Dquarkus.build.output.directory=/tmp/quarkus-build
Defensive patterns

Strategy: validation

Validate before calling

Path protoOutputDir = buildDir.resolve("proto-extracted");
if (!Files.isDirectory(protoOutputDir) && !protoOutputDir.toFile().mkdirs() && !Files.isWritable(buildDir)) {
    throw new IllegalStateException("Cannot create/write " + protoOutputDir + " — check permissions and disk space");
}

Try / catch

try {
    // run build / trigger codegen
} catch (CodeGenException e) {
    if (e.getMessage().startsWith("Failed to create directory")) {
        log.error("Fix permissions/disk for: " + e.getCause(), e);
    }
}

Prevention

When it happens

Trigger: Calling quarkus generate-code (or mvn compile / quarkus:dev) with quarkus.generate-code.grpc.scan-for-imports configured so a dependency JAR containing .proto files is scanned, and the JVM cannot create the hashed work directory under target/classes or the build output directory.

Common situations: Read-only CI workspaces; a stale file occupying the same path as the directory; overly long paths on Windows; a full disk or restrictive umask; running the build as a different user than the one owning target/.

Related errors


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