oracle/graal · error · PermanentBailoutException

Compilation exceeded %.3f seconds%s. %n Phase timings:%n %s

Error message

Compilation exceeded %.3f seconds%s. %n Phase timings:%n %s <===== TIMEOUT HERE

What it means

CompilationAlarm throws this PermanentBailoutException when a Graal compilation runs longer than its configured time budget (the alarm's period). The message includes total elapsed seconds, optional GC time, and a phase-timing tree marking the phase that was active when the alarm fired ('<===== TIMEOUT HERE'). Permanent bailout means the compilation is abandoned and (in a JVM setting) the method falls back to a lower tier rather than crashing.

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/CompilationAlarm.java:207

            /*
             * We clone the phase tree here for the sake of the error message. We want to fix up the
             * root timings and also annotate in which phase(s) the timeout happens. We do not do
             * this on the original tree because that one can still be in IGV dumps.
             */
            PhaseTreeNode cloneTree = cloneTree(root, null);
            StringBuilder sb = new StringBuilder();
            // also update the root time to be consistent for the error message
            cloneTree.durationNS = elapsed();
            printTree("", sb, cloneTree, true, skipZeros);

            // Include information about time spent in the GC if it's available.
            String gcMessage = "";
            if (gcTiming != null) {
                gcMessage = String.format(" (GC time is %s ms of %s ms elapsed)", gcTiming.getGCTimeMillis(), gcTiming.getElapsedTimeMillis());
            }

            throw new PermanentBailoutException("Compilation exceeded %.3f seconds%s. %n Phase timings:%n %s <===== TIMEOUT HERE", period, gcMessage, sb.toString().trim());
        }
    }

    @Override
    public void close() {
        currentAlarm.set(previous);
        resetProgressDetection();
    }

    /**
     * Expiration period (in seconds) of this alarm.
     */
    private double period;

    /**
     * The time at which this alarm expires in nanoseconds.
     */
    private long expirationNS;

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Read the phase-timing tree in the message: it names the phase that hit the limit — that is where the investigation (or bug report) should focus.
  2. Raise or disable the compilation time limit option that armed the alarm (check the embedding VM's / Graal's option for the alarm period) if the machine is legitimately slow.
  3. Exclude the offending method from Graal compilation (-XX:CompileCommand=exclude) or shrink it / limit inlining (-Dgraal.MaximumDesiredSize, -Dgraal.LimitInlinedCalls) so it compiles within budget.
  4. If the timing tree shows one phase dominating on a normal method, file a Graal performance issue with the graph dump.
Defensive patterns

Strategy: try-catch

Try / catch

// in an embedding host: permanent bailouts are expected, catch and fall back
try {
    result = graalCompile(graph);
} catch (PermanentBailoutException e) {
    if (e.getMessage().contains("Compilation exceeded")) {
        result = baselineCompile(graph); // or retry with inlining disabled
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: A compilation exceeding the limit configured for the alarm (e.g. via Graal's compilation time limit options such as -Dgraal.CompilationTimeLimit-style settings, or the alarm set by the embedding VM with a specific period). Slow phases like huge inlining, scheduling, or register allocation on very large graphs trip it; the printed phase tree identifies which phase consumed the budget.

Common situations: Compiling giant generated methods (template engines, serialization codegen, genetic/DSL output), pathological inlining blowups, or simply overloaded CI machines where wall-clock budgets are exceeded. Also seen after upgrades that regress a phase's complexity, or on very slow/emulated hardware (QEMU) where time-based limits calibrated for native speed fire spuriously.

Understand the failure class

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/271980c6b40574a3. Report an issue: GitHub.