Code review comment: I'm not familiar with this API, but is it safe to expect the input stream to contain the full output when the process is already terminated?

Code under review:
public void provideOutcome(AppCreator ctx) throws AppCreatorException {

        outputDir = outputDir == null ? ctx.getWorkPath() : IoUtils.mkdirs(outputDir);

        final RunnerJarOutcome runnerJarOutcome = ctx.resolveOutcome(RunnerJarOutcome.class);
        Path runnerJar = runnerJarOutcome.getRunnerJar();
        boolean runnerJarCopied = false;
        
        if (!runnerJar.getParent().equals(outputDir)) {
            try {
                runnerJar = IoUtils.copy(runnerJar, outputDir.resolve(runnerJar.getFileName()));
            } catch (IOException e) {
                throw new AppCreatorException("Failed to copy the runnable jar to the output dir", e);
            }
            runnerJarCopied = true;
        }
        final String runnerJarName = runnerJar.getFileName().toString();

        Path outputLibDir = outputDir.resolve(runnerJarOutcome.getLibDir().getFileName());
        boolean outputLibDirCopied = false;
        if (Files.exists(outputLibDir)) {
            outputLibDir = null;
        } else {
            try {
                IoUtils.copy(runnerJarOutcome.getLibDir(), outputLibDir);
            } catch (IOException e) {
                throw new AppCreatorException("Failed to copy the runnable jar and the lib to the docker project dir", e);
            }
            outputLibDirCopied = true;
        }

        final Config config = SmallRyeConfigProviderResolver.instance().getConfig();

        boolean vmVersionOutOfDate = isThisGraalVMRCObsolete();

        HashMap<String, String> env = new HashMap<>(System.getenv());
        List<String> nativeImage;

        String noPIE = "";

        if (!"".equals(containerRuntime)) {
            
            nativeImage = new ArrayList<>();
            Collections.addAll(nativeImage, containerRuntime, "run", "-v", outputDir.toAbsolutePath() + ":/project:z", "--rm");
            if (IS_LINUX & "docker".equals(containerRuntime)) {
                try {
                    BufferedReader reader;
                    StringBuilder builder;
                    String uid = null;
                    String gid = null;

                    ProcessBuilder idPB = new ProcessBuilder().command("id", "-ur");
                    Process process = idPB.start();

                    if (process.waitFor() == 0) {
                        reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                        builder = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            builder.append(line);
                        }
                        uid = builder.toString();
                    }

                    idPB = new ProcessBuilder().command("id", "-gr");
                    process = idPB.start();

                    if (process.waitFor() == 0) {
                        reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                        builder = new StringBuilder();
                        String line = null;
                        while ((line = reader.readLine()) != null) {
                            builder.append(line);
                        }
                        gid = builder.toString();
                    }

                    if (uid != null & gid != null & !"".equals(uid) & !"".equals(gid)) {
                        Collections.addAll(nativeImage, "--user", uid.concat(":").concat(gid));
                    }
                } catch (Exception e) {
                    
                }
            }
            nativeImage.addAll(containerRuntimeOptions);
            nativeImage.add(this.builderImage);
        } else {
            if (IS_LINUX) {
                noPIE = detectNoPIE();
            }

            String graalvmHome = this.graalvmHome;
            if (graalvmHome != null) {
                env.put(GRAALVM_HOME, graalvmHome);
            } else {
                graalvmHome = env.get(GRAALVM_HOME);
                if (graalvmHome == null) {
                    throw new AppCreatorException("GRAALVM_HOME was not set");
                }
            }
            nativeImage = Collections.singletonList(graalvmHome + File.separator + "bin" + File.separator + "native-image");
        }

        try {
            List<String> command = new ArrayList<>();
            command.addAll(nativeImage);
            if (cleanupServer) {
                List<String> cleanup = new ArrayList<>(nativeImage);
                cleanup.add("--server-shutdown");
                ProcessBuilder pb = new ProcessBuilder(cleanup.toArray(new String[0]));
                pb.directory(outputDir.toFile());
                pb.redirectInput(ProcessBuilder.Redirect.INHERIT);
                pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
                pb.redirectError(ProcessBuilder.Redirect.INHERIT);
                Process process = pb.start();
                process.waitFor();
            }
            
            final Path propsFile = ctx.resolveOutcome(AugmentOutcome.class).getAppClassesDir()
                    .resolve("native-image.properties");

            boolean enableSslNative = false;
            if (Files.exists(propsFile)) {
                final Properties properties = new Properties();
                try (BufferedReader reader = Files.newBufferedReader(propsFile, StandardCharsets.UTF_8)) {
                    properties.load(reader);
                }
                for (String propertyName : properties.stringPropertyNames()) {
                    if (propertyName.startsWith(QUARKUS_PREFIX)) {
                        continue;
                    }

                    final String propertyValue = properties.getProperty(propertyName);
                    
                    if (propertyValue == null) {
                        command.add("-J-D" + propertyName);
                    } else {
                        command.add("-J-D" + propertyName + "=" + propertyValue);
                    }
                }

                enableSslNative = properties.getProperty("quarkus.ssl.native") != null
                        ? Boolean.parseBoolean(properties.getProperty("quarkus.ssl.native"))
                        : false;
            }
            if (enableSslNative) {
                enableHttpsUrlHandler = true;
                enableJni = true;
                enableAllSecurityServices = true;
            }
            if (additionalBuildArgs != null) {
                additionalBuildArgs.forEach(command::add);
            }
            command.add("-H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy$BySpaceAndTime"); 
            command.add("-jar");
            command.add(runnerJarName);
            
            command.add("-J-Djava.util.concurrent.ForkJoinPool.common.parallelism=1");
            if (reportErrorsAtRuntime) {
                command.add("-H:+ReportUnsupportedElementsAtRuntime");
            }
            if (debugSymbols) {
                command.add("-g");
            }
            if (debugBuildProcess) {
                command.add("-J-Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=y");
            }
            if (!disableReports) {
                command.add("-H:+PrintAnalysisCallTree");
            }
            if (dumpProxies) {
                command.add("-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true");
                if (enableServer) {
                    log.warn(
                            "Options dumpProxies and enableServer are both enabled: this will get the proxies dumped in an unknown external working directory");
                }
            }
            if (nativeImageXmx != null) {
                command.add("-J-Xmx" + nativeImageXmx);
            }
            List<String> protocols = new ArrayList<>(2);
            if (enableHttpUrlHandler) {
                protocols.add("http");
            }
            if (enableHttpsUrlHandler) {
                protocols.add("https");
            }
            if (addAllCharsets) {
                command.add("-H:+AddAllCharsets");
            } else {
                command.add("-H:-AddAllCharsets");
            }
            if (!protocols.isEmpty()) {
                command.add("-H:EnableURLProtocols=" + String.join(",", protocols));
            }
            if (enableAllSecurityServices) {
                command.add("--enable-all-security-services");
            }
            if (!noPIE.isEmpty()) {
                command.add("-H:NativeLinkerOption=" + noPIE);
            }
            if (enableRetainedHeapReporting) {
                command.add("-H:+PrintRetainedHeapHistogram");
            }
            if (enableCodeSizeReporting) {
                command.add("-H:+PrintCodeSizeReport");
            }
            if (!enableIsolates) {
                command.add("-H:-SpawnIsolates");
            }
            if (enableJni) {
                command.add("-H:+JNI");
            } else {
                command.add("-H:-JNI");
            }
            if (!enableServer) {
                command.add("--no-server");
            }
            if (enableVMInspection) {
                command.add("-H:+AllowVMInspection");
            }
            if (autoServiceLoaderRegistration) {
                command.add("-H:+UseServiceLoaderFeature");
                
                command.add("-H:+TraceServiceLoaderFeature");
            } else {
                command.add("-H:-UseServiceLoaderFeature");
            }
            if (fullStackTraces) {
                command.add("-H:+StackTrace");
            } else {
                command.add("-H:-StackTrace");
            }

            log.info(command.stream().collect(Collectors.joining(" ")));
            CountDownLatch errorReportLatch = new CountDownLatch(1);

            ProcessBuilder pb = new ProcessBuilder(command.toArray(new String[0]));
            pb.directory(outputDir.toFile());
            pb.redirectInput(ProcessBuilder.Redirect.INHERIT);
            pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);

            Process process = pb.start();
            new Thread(new ErrorReplacingProcessReader(process.getErrorStream(), outputDir.resolve("reports").toFile(),
                    errorReportLatch)).start();
            errorReportLatch.await();
            if (process.waitFor() != 0) {
                throw new RuntimeException("Image generation failed");
            }
            System.setProperty("native.image.path", runnerJarName.substring(0, runnerJarName.lastIndexOf('.')));

            ctx.pushOutcome(NativeImageOutcome.class, this);
        } catch (Exception e) {
            throw new AppCreatorException("Failed to build native image", e);
        } finally {
            if (runnerJarCopied) {
                IoUtils.recursiveDelete(runnerJar);
            }
            if (outputLibDirCopied) {
                IoUtils.recursiveDelete(outputLibDir);
            }
        }
    }

Line commented on: reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

Revised code:
public void provideOutcome(AppCreator ctx) throws AppCreatorException {

        outputDir = outputDir == null ? ctx.getWorkPath() : IoUtils.mkdirs(outputDir);

        final RunnerJarOutcome runnerJarOutcome = ctx.resolveOutcome(RunnerJarOutcome.class);
        Path runnerJar = runnerJarOutcome.getRunnerJar();
        boolean runnerJarCopied = false;
        
        if (!runnerJar.getParent().equals(outputDir)) {
            try {
                runnerJar = IoUtils.copy(runnerJar, outputDir.resolve(runnerJar.getFileName()));
            } catch (IOException e) {
                throw new AppCreatorException("Failed to copy the runnable jar to the output dir", e);
            }
            runnerJarCopied = true;
        }
        final String runnerJarName = runnerJar.getFileName().toString();

        Path outputLibDir = outputDir.resolve(runnerJarOutcome.getLibDir().getFileName());
        boolean outputLibDirCopied = false;
        if (Files.exists(outputLibDir)) {
            outputLibDir = null;
        } else {
            try {
                IoUtils.copy(runnerJarOutcome.getLibDir(), outputLibDir);
            } catch (IOException e) {
                throw new AppCreatorException("Failed to copy the runnable jar and the lib to the docker project dir", e);
            }
            outputLibDirCopied = true;
        }

        final Config config = SmallRyeConfigProviderResolver.instance().getConfig();

        boolean vmVersionOutOfDate = isThisGraalVMRCObsolete();

        HashMap<String, String> env = new HashMap<>(System.getenv());
        List<String> nativeImage;

        String noPIE = "";

        if (!"".equals(containerRuntime)) {
            
            nativeImage = new ArrayList<>();
            Collections.addAll(nativeImage, containerRuntime, "run", "-v", outputDir.toAbsolutePath() + ":/project:z", "--rm");

            if (IS_LINUX & "docker".equals(containerRuntime)) {
                String uid = getLinuxID("-ur");
                String gid = getLinuxID("-gr");
                if (uid != null & gid != null & !"".equals(uid) & !"".equals(gid)) {
                    Collections.addAll(nativeImage, "--user", uid.concat(":").concat(gid));
                }
            }
            nativeImage.addAll(containerRuntimeOptions);
            nativeImage.add(this.builderImage);
        } else {
            if (IS_LINUX) {
                noPIE = detectNoPIE();
            }

            String graalvmHome = this.graalvmHome;
            if (graalvmHome != null) {
                env.put(GRAALVM_HOME, graalvmHome);
            } else {
                graalvmHome = env.get(GRAALVM_HOME);
                if (graalvmHome == null) {
                    throw new AppCreatorException("GRAALVM_HOME was not set");
                }
            }
            nativeImage = Collections.singletonList(graalvmHome + File.separator + "bin" + File.separator + "native-image");
        }

        try {
            List<String> command = new ArrayList<>();
            command.addAll(nativeImage);
            if (cleanupServer) {
                List<String> cleanup = new ArrayList<>(nativeImage);
                cleanup.add("--server-shutdown");
                ProcessBuilder pb = new ProcessBuilder(cleanup.toArray(new String[0]));
                pb.directory(outputDir.toFile());
                pb.redirectInput(ProcessBuilder.Redirect.INHERIT);
                pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
                pb.redirectError(ProcessBuilder.Redirect.INHERIT);
                Process process = pb.start();
                process.waitFor();
            }
            
            final Path propsFile = ctx.resolveOutcome(AugmentOutcome.class).getAppClassesDir()
                    .resolve("native-image.properties");

            boolean enableSslNative = false;
            if (Files.exists(propsFile)) {
                final Properties properties = new Properties();
                try (BufferedReader reader = Files.newBufferedReader(propsFile, StandardCharsets.UTF_8)) {
                    properties.load(reader);
                }
                for (String propertyName : properties.stringPropertyNames()) {
                    if (propertyName.startsWith(QUARKUS_PREFIX)) {
                        continue;
                    }

                    final String propertyValue = properties.getProperty(propertyName);
                    
                    if (propertyValue == null) {
                        command.add("-J-D" + propertyName);
                    } else {
                        command.add("-J-D" + propertyName + "=" + propertyValue);
                    }
                }

                enableSslNative = properties.getProperty("quarkus.ssl.native") != null
                        ? Boolean.parseBoolean(properties.getProperty("quarkus.ssl.native"))
                        : false;
            }
            if (enableSslNative) {
                enableHttpsUrlHandler = true;
                enableJni = true;
                enableAllSecurityServices = true;
            }
            if (additionalBuildArgs != null) {
                additionalBuildArgs.forEach(command::add);
            }
            command.add("-H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy$BySpaceAndTime"); 
            command.add("-jar");
            command.add(runnerJarName);
            
            command.add("-J-Djava.util.concurrent.ForkJoinPool.common.parallelism=1");
            if (reportErrorsAtRuntime) {
                command.add("-H:+ReportUnsupportedElementsAtRuntime");
            }
            if (debugSymbols) {
                command.add("-g");
            }
            if (debugBuildProcess) {
                command.add("-J-Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=y");
            }
            if (!disableReports) {
                command.add("-H:+PrintAnalysisCallTree");
            }
            if (dumpProxies) {
                command.add("-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true");
                if (enableServer) {
                    log.warn(
                            "Options dumpProxies and enableServer are both enabled: this will get the proxies dumped in an unknown external working directory");
                }
            }
            if (nativeImageXmx != null) {
                command.add("-J-Xmx" + nativeImageXmx);
            }
            List<String> protocols = new ArrayList<>(2);
            if (enableHttpUrlHandler) {
                protocols.add("http");
            }
            if (enableHttpsUrlHandler) {
                protocols.add("https");
            }
            if (addAllCharsets) {
                command.add("-H:+AddAllCharsets");
            } else {
                command.add("-H:-AddAllCharsets");
            }
            if (!protocols.isEmpty()) {
                command.add("-H:EnableURLProtocols=" + String.join(",", protocols));
            }
            if (enableAllSecurityServices) {
                command.add("--enable-all-security-services");
            }
            if (!noPIE.isEmpty()) {
                command.add("-H:NativeLinkerOption=" + noPIE);
            }
            if (enableRetainedHeapReporting) {
                command.add("-H:+PrintRetainedHeapHistogram");
            }
            if (enableCodeSizeReporting) {
                command.add("-H:+PrintCodeSizeReport");
            }
            if (!enableIsolates) {
                command.add("-H:-SpawnIsolates");
            }
            if (enableJni) {
                command.add("-H:+JNI");
            } else {
                command.add("-H:-JNI");
            }
            if (!enableServer) {
                command.add("--no-server");
            }
            if (enableVMInspection) {
                command.add("-H:+AllowVMInspection");
            }
            if (autoServiceLoaderRegistration) {
                command.add("-H:+UseServiceLoaderFeature");
                
                command.add("-H:+TraceServiceLoaderFeature");
            } else {
                command.add("-H:-UseServiceLoaderFeature");
            }
            if (fullStackTraces) {
                command.add("-H:+StackTrace");
            } else {
                command.add("-H:-StackTrace");
            }

            log.info(command.stream().collect(Collectors.joining(" ")));
            CountDownLatch errorReportLatch = new CountDownLatch(1);

            ProcessBuilder pb = new ProcessBuilder(command.toArray(new String[0]));
            pb.directory(outputDir.toFile());
            pb.redirectInput(ProcessBuilder.Redirect.INHERIT);
            pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);

            Process process = pb.start();
            new Thread(new ErrorReplacingProcessReader(process.getErrorStream(), outputDir.resolve("reports").toFile(),
                    errorReportLatch)).start();
            errorReportLatch.await();
            if (process.waitFor() != 0) {
                throw new RuntimeException("Image generation failed");
            }
            System.setProperty("native.image.path", runnerJarName.substring(0, runnerJarName.lastIndexOf('.')));

            ctx.pushOutcome(NativeImageOutcome.class, this);
        } catch (Exception e) {
            throw new AppCreatorException("Failed to build native image", e);
        } finally {
            if (runnerJarCopied) {
                IoUtils.recursiveDelete(runnerJar);
            }
            if (outputLibDirCopied) {
                IoUtils.recursiveDelete(outputLibDir);
            }
        }
    }