{"record":{"id":"5a2998ce0422dc4e","repo":"oracle/graal","slug":"observed-identical-stack-traces-for-d-ms-indicat","errorCode":null,"errorMessage":"Observed identical stack traces for %d ms, indicating a stuck compilation, counter = %s, stack is:%n%s","messagePattern":"Observed identical stack traces for (.+?) ms, indicating a stuck compilation, counter = (.+?), stack is:%n(.+?)","errorType":"exception","errorClass":"PermanentBailoutException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/CompilationAlarm.java","lineNumber":668,"sourceCode":"        }\n\n        assert Arrays.equals(lastStackTrace, currentStackTrace) : \"Must only enter this branch if no progress was made\";\n        /*\n         * We have a similar stack trace - fail once the period is longer than the no progress\n         * period.\n         */\n        final long lastUniqueStackTraceTime = lastUniqueStackTraceForThreadNS.get();\n        final long nowNS = System.nanoTime();\n        final long elapsedNS = nowNS - lastUniqueStackTraceTime;\n        boolean stuck = elapsedNS > stuckThreshold;\n\n        if (LOG_PROGRESS_DETECTION) {\n            TTY.printf(\"CompilationAlarm: Progress detection %s; no progress for %d ms; stuck? %s; stuck threshold %d ms%n\",\n                            counter, TimeUnit.NANOSECONDS.toMillis(elapsedNS), stuck, stuckThreshold);\n        }\n\n        if (stuck) {\n            throw new PermanentBailoutException(\"Observed identical stack traces for %d ms, indicating a stuck compilation, counter = %s, stack is:%n%s\",\n                            TimeUnit.NANOSECONDS.toMillis(elapsedNS), counter, Util.toString(lastStackTrace));\n        }\n    }\n\n    public static void resetProgressDetection() {\n        lastStackTraceForThread.set(null);\n        lastUniqueStackTraceForThreadNS.set(null);\n        lastMarkerForThread.set(null);\n        noProgressStartPeriodNS.set(null);\n    }\n\n    private static final ThreadLocal<StackTraceElement[]> lastStackTraceForThread = new ThreadLocal<>();\n    private static final ThreadLocal<Long> lastUniqueStackTraceForThreadNS = new ThreadLocal<>();\n    /**\n     * Note that all these thread locals are not necessarily reset for a while even if worker\n     * threads have moved on to do actual work (but just not compiling graphs). Especially in the\n     * native image generator, not all {@link #assertProgress} calls can be in a closeable scope\n     * that invokes {@link #resetProgressDetection}. It is therefore critical that they do not keep","sourceCodeStart":650,"sourceCodeEnd":686,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/CompilationAlarm.java#L650-L686","documentation":"CompilationAlarm's progress detection periodically samples the compiling thread's stack trace; if the same stack persists longer than the stuck threshold (a wall-clock duration measured from the last unique trace), it concludes the compilation is not making progress and throws this PermanentBailoutException with the elapsed ms, the alarm counter, and the frozen stack. Like error 28 it aborts just the compilation, not the VM.","triggerScenarios":"A single compilation thread executing one phase for longer than the stuck threshold without the stack changing — typically a super-linear algorithm inside one optimization phase (e.g. a quadratic loop in scheduling, inlining, or graph cleanup) on a very large graph. Repeated samples return identical StackTraceElements, crossing the threshold.","commonSituations":"Large generated methods or adversarial benchmarks that trigger complexity blowups in a Graal phase; regressions after a Graal upgrade; heavily loaded machines where the stuck threshold is too aggressive for slow-but-progressing compilations. The frozen stack in the message names the exact method and line that was spinning.","solutions":["Use the stack trace embedded in the message to identify the looping phase/line, and file a Graal issue with it — a truly stuck compilation is a compiler bug.","Exclude the affected method from Graal compilation so the baseline compiler handles it.","If the compilation is slow but progressing (loaded CI box), raise or disable the progress-detection/stuck threshold option before disabling the feature wholesale.","Reduce input size (smaller method, less inlining) so the phase completes between samples."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    result = graalCompile(graph);\n} catch (PermanentBailoutException e) {\n    if (e.getMessage().contains(\"stuck compilation\")) {\n        bugTracker.attach(e.getMessage()); // message contains the frozen stack\n        result = baselineCompile(graph);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Harvest the embedded stack trace — it is exactly the evidence a compiler bug report needs.","Keep a corpus of the largest methods your product compiles and run it through new Graal builds to catch non-linear phase blowups early.","On heavily loaded machines, scale the stuck threshold with measured compile throughput."],"tags":["stuck-compilation","bailout","progress-detection","performance","compiler"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}