quarkusio/quarkus · error · IllegalStateException

Build report file cannot be written to:

Error message

Build report file cannot be written to: 

What it means

BuildReport.generate writes build-report.html into the build tool's build directory; if the file already exists but is not writable it throws IllegalStateException 'Build report file cannot be written to: <path>'. A subsequent IOException while writing is also surfaced from this method.

Source

Thrown at devtools/cli/src/main/java/io/quarkus/cli/BuildReport.java:69

            JsonNode produced = record.get("producedItems");
            if (produced != null && !(produced instanceof NullNode)) {
                producedItems = new ArrayList<>();
                for (JsonNode item : produced) {
                    producedItems.add(new BuildItem(item.get("item").asText(), item.get("count").asInt()));
                }
            }
            records.add(new BuildStepRecord(record.get("stepId").asText(), record.get("started").asText(),
                    record.get("duration").asLong(), thread, producedItems));
        }

        for (JsonNode item : root.get("items")) {
            items.add(new BuildItem(item.get("class").asText(), item.get("count").asInt()));
        }

        File output = runner.getProjectRoot().resolve(runner.getBuildTool().getBuildDirectory())
                .resolve("build-report.html").toFile();
        if (output.exists() && !output.canWrite()) {
            throw new IllegalStateException("Build report file cannot be written to: " + output);
        }
        try {
            Files.writeString(output.toPath(),
                    BuildReport.buildReport(buildTarget, duration, threads, records, items, itemsCount).render());
            return output;
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
    }

    public static class BuildStepRecord {

        public final String stepId;
        public final String started;
        public final long duration;
        public final String thread;
        public final List<BuildItem> producedItems;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Fix permissions on the existing build-report.html (chmod u+w) or delete it before regenerating
  2. Run the command as the user who owns the build directory (or chown the directory)
  3. Ensure the build/target directory is on a writable filesystem
  4. If in a container, avoid building as root or adjust volume mount permissions

Example fix

# before: permission denied on stale report
sudo chown -R $USER target/
rm -f target/build-report.html
./quarkus build --report
Defensive patterns

Strategy: validation

Validate before calling

File out = new File(buildDir, "build-report.html");
if (out.exists() && !out.canWrite()) throw new IllegalStateException("Fix permissions on " + out);

Try / catch

try { report.generate(); } catch (IllegalStateException e) { if (e.getMessage().startsWith("Build report file cannot be written")) { new File(e.getMessage().substring(e.getMessage().lastIndexOf(':')+1).trim()).delete(); report.generate(); } else throw e; }

Prevention

When it happens

Trigger: Regenerating the report where build-report.html exists but the current user lacks write permission, the file is owned by another user (e.g. root-built output), or the filesystem is read-only.

Common situations: Previous build ran as root/in a container, leaving read-only output; CI workspace permissions changed; running on a mounted read-only target directory.

Related errors


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