quarkusio/quarkus · error · IllegalStateException

Build metrics file cannot be read:

Error message

Build metrics file cannot be read: 

What it means

quarkus build --report (BuildReport.generate) reads <buildDir>/build-metrics.json produced by the build tool; if the file is absent or unreadable it throws IllegalStateException 'Build metrics file cannot be read: <path>'. The report generation requires metrics emitted by the preceding build.

Source

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

import tools.jackson.databind.node.NullNode;

@CheckedTemplate(basePath = "")
public class BuildReport {

    static native TemplateInstance buildReport(String buildTarget, long duration, Set<String> threads,
            List<BuildStepRecord> records, List<BuildItem> buildItems, int buildItemsCount);

    private final BuildSystemRunner runner;

    public BuildReport(BuildSystemRunner runner) {
        this.runner = runner;
    }

    File generate() throws IOException {
        File metricsJsonFile = runner.getProjectRoot().resolve(runner.getBuildTool().getBuildDirectory())
                .resolve("build-metrics.json").toFile();
        if (!metricsJsonFile.canRead()) {
            throw new IllegalStateException("Build metrics file cannot be read: " + metricsJsonFile);
        }

        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode root = objectMapper.readTree(metricsJsonFile);

        String buildTarget = root.get("buildTarget").asText();
        long duration = root.get("duration").asLong();
        Set<String> threads = new HashSet<>();
        List<BuildStepRecord> records = new ArrayList<>();
        List<BuildItem> items = new ArrayList<>();
        int itemsCount = root.get("itemsCount").asInt();

        for (JsonNode record : root.get("records")) {
            String thread = record.get("thread").asText();
            threads.add(thread);
            List<BuildItem> producedItems = List.of();
            JsonNode produced = record.get("producedItems");
            if (produced != null && !(produced instanceof NullNode)) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Run the build first (e.g. ./mvnw package or gradlew build) so build-metrics.json is generated, then generate the report
  2. Verify you run the command from the project root so the metrics path resolves correctly
  3. Check that <buildDir>/build-metrics.json exists and is readable (ls/target/build dir)
  4. Ensure the build tool's build directory hasn't been customized without updating expectations

Example fix

# before: report without build
./quarkus build --report   # fails, no build-metrics.json
# after
./mvnw package -DskipTests && ./quarkus build --report
Defensive patterns

Strategy: validation

Validate before calling

File metrics = new File(buildDir, "build-metrics.json");
if (!metrics.canRead()) throw new IllegalStateException("Build first so build-metrics.json exists at " + metrics);

Try / catch

try { report.generate(); } catch (IllegalStateException e) { if (e.getMessage().startsWith("Build metrics file cannot be read")) System.err.println("Run the build before generating a report"); else throw e; }

Prevention

When it happens

Trigger: Running the build-report command/request without a prior successful build that wrote build-metrics.json, running from the wrong project root/build tool, or deleting the target/build directory before generating the report.

Common situations: Forgetting to build first; running report generation after `mvn clean`; project root misdetected (running CLI outside the project directory); build tool's build directory customized.

Related errors


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