{"record":{"id":"57adf47d10f92acb","repo":"quarkusio/quarkus","slug":"failed-to-create-directory-protooutputdir","errorCode":null,"errorMessage":"Failed to create directory: \" + protoOutputDir","messagePattern":"Failed to create directory: \" \\+ protoOutputDir","errorType":"exception","errorClass":"GrpcCodeGenException","httpStatus":null,"severity":"error","filePath":"extensions/grpc/codegen/src/main/java/io/quarkus/grpc/codegen/GrpcCodeGen.java","lineNumber":418,"sourceCode":"            Set<String> protoDirectories, ResolvedDependency artifact, Collection<String> filesToInclude,\n            Collection<String> filesToExclude, boolean isDependency) throws CodeGenException {\n\n        // Proto files from dependencies are always copied to a work directory with known\n        // path prefixes (src/main/proto/, src/test/proto/, proto/) stripped. This ensures\n        // consistent --proto_path entries for protoc regardless of whether the artifact\n        // resolved to a JAR (archive) or a directory (e.g. workspace project's target/classes).\n        Path protoOutputDir = getProtoOutputDir(workDir, artifact);\n        try {\n            artifact.getContentTree(new PathFilter(filesToInclude, filesToExclude)).walk(\n                    pathVisit -> {\n                        Path path = pathVisit.getPath();\n                        if (Files.isRegularFile(path) && path.getFileName().toString().endsWith(PROTO)) {\n                            String strippedPathStr = stripProtoPrefix(pathVisit.getResourceName());\n                            try {\n                                Files.createDirectories(protoOutputDir);\n                                protoDirectories.add(protoOutputDir.toString());\n                            } catch (IOException e) {\n                                throw new GrpcCodeGenException(\"Failed to create directory: \" + protoOutputDir, e);\n                            }\n                            Path outPath = protoOutputDir.resolve(strippedPathStr);\n                            try {\n                                Files.createDirectories(outPath.getParent());\n                                if (isDependency) {\n                                    copySanitizedProtoFile(artifact, path, outPath);\n                                } else {\n                                    Files.copy(path, outPath, StandardCopyOption.REPLACE_EXISTING);\n                                }\n                                protoFiles.add(outPath);\n                            } catch (IOException e) {\n                                throw new GrpcCodeGenException(\"Failed to extract proto file\" + path + \" to target: \"\n                                        + outPath, e);\n                            }\n                        }\n                    });\n        } catch (GrpcCodeGenException e) {\n            throw new CodeGenException(e.getMessage(), e);","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/grpc/codegen/src/main/java/io/quarkus/grpc/codegen/GrpcCodeGen.java#L400-L436","documentation":"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.","triggerScenarios":"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.","commonSituations":"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/.","solutions":["Check permissions/ownership of the build output directory (e.g. target/) and ensure the build user can write to it","Run mvn clean (or gradle clean) to remove stale conflicting files, then rebuild","Check disk space with df -h; free space if the volume is full","On Windows, shorten the project path or enable long-path support to avoid MAX_PATH issues","If the directory is read-only in CI, add a writable workspace/volume for the build"],"exampleFix":"// before: building in a read-only CI checkout\nmvn -Dmaven.repo.local=/ro/repo compile\n// after: point output to a writable location and clean first\nmvn clean compile -Dquarkus.build.output.directory=/tmp/quarkus-build","handlingStrategy":"validation","validationCode":"Path protoOutputDir = buildDir.resolve(\"proto-extracted\");\nif (!Files.isDirectory(protoOutputDir) && !protoOutputDir.toFile().mkdirs() && !Files.isWritable(buildDir)) {\n    throw new IllegalStateException(\"Cannot create/write \" + protoOutputDir + \" — check permissions and disk space\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    // run build / trigger codegen\n} catch (CodeGenException e) {\n    if (e.getMessage().startsWith(\"Failed to create directory\")) {\n        log.error(\"Fix permissions/disk for: \" + e.getCause(), e);\n    }\n}","preventionTips":["Ensure the build user owns target/ and has write permissions","Monitor disk space before CI builds","Avoid Windows MAX_PATH by keeping projects in short paths","Clean stale builds with mvn clean rather than editing target/ by hand"],"tags":["io","filesystem","build","grpc","codegen"],"backgroundTag":"directory-creation-failed","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}