{"record":{"id":"271980c6b40574a3","repo":"oracle/graal","slug":"compilation-exceeded-3f-seconds-s-n-phase-timi","errorCode":null,"errorMessage":"Compilation exceeded %.3f seconds%s. %n Phase timings:%n %s <===== TIMEOUT HERE","messagePattern":"Compilation exceeded %\\.3f seconds(.+?)\\. %n Phase timings:%n (.+?) <===== TIMEOUT HERE","errorType":"exception","errorClass":"PermanentBailoutException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/CompilationAlarm.java","lineNumber":207,"sourceCode":"\n            /*\n             * We clone the phase tree here for the sake of the error message. We want to fix up the\n             * root timings and also annotate in which phase(s) the timeout happens. We do not do\n             * this on the original tree because that one can still be in IGV dumps.\n             */\n            PhaseTreeNode cloneTree = cloneTree(root, null);\n            StringBuilder sb = new StringBuilder();\n            // also update the root time to be consistent for the error message\n            cloneTree.durationNS = elapsed();\n            printTree(\"\", sb, cloneTree, true, skipZeros);\n\n            // Include information about time spent in the GC if it's available.\n            String gcMessage = \"\";\n            if (gcTiming != null) {\n                gcMessage = String.format(\" (GC time is %s ms of %s ms elapsed)\", gcTiming.getGCTimeMillis(), gcTiming.getElapsedTimeMillis());\n            }\n\n            throw new PermanentBailoutException(\"Compilation exceeded %.3f seconds%s. %n Phase timings:%n %s <===== TIMEOUT HERE\", period, gcMessage, sb.toString().trim());\n        }\n    }\n\n    @Override\n    public void close() {\n        currentAlarm.set(previous);\n        resetProgressDetection();\n    }\n\n    /**\n     * Expiration period (in seconds) of this alarm.\n     */\n    private double period;\n\n    /**\n     * The time at which this alarm expires in nanoseconds.\n     */\n    private long expirationNS;","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/CompilationAlarm.java#L189-L225","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","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.","Exclude the offending method from Graal compilation (-XX:CompileCommand=exclude) or shrink it / limit inlining (-Dgraal.MaximumDesiredSize, -Dgraal.LimitInlinedCalls) so it compiles within budget.","If the timing tree shows one phase dominating on a normal method, file a Graal performance issue with the graph dump."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// in an embedding host: permanent bailouts are expected, catch and fall back\ntry {\n    result = graalCompile(graph);\n} catch (PermanentBailoutException e) {\n    if (e.getMessage().contains(\"Compilation exceeded\")) {\n        result = baselineCompile(graph); // or retry with inlining disabled\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always implement a fallback tier when embedding Graal — PermanentBailoutException is by design recoverable.","Size the alarm period to the slowest expected machine in your fleet, not the fastest.","Watch the phase-timing tree in the message over time to spot creeping phase regressions."],"tags":["compilation-timeout","bailout","performance","phase-timings","compiler"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}