graal icon indicating copy to clipboard operation
graal copied to clipboard

[Native Image] Possible race condition in InterceptJSInvokeTypeFlow causes intermittent build failures

Open willcohen opened this issue 1 month ago • 3 comments

Describe the Issue

Intermittent build failure (~80% failure rate) in native-image --tool:svm-wasm with "Should not reach here" error. The failure is non-deterministic - running the same build multiple times produces different results.

Using the latest version of GraalVM can resolve many issues.

GraalVM Version

java 26 2026-03-17 Java(TM) SE Runtime Environment Oracle GraalVM 26-dev+13.1 (build 26+13-jvmci-b01) Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 26-dev+13.1 (build 26+13-jvmci-b01, mixed mode, sharing)

Operating System and Version

25.1.0 Darwin Kernel Version 25.1.0: Mon Oct 20 19:34:03 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T8112 arm64

Build Command

I unfortunately cannot provide a minimal repro -- it appears to trigger after a certain level of complexity, but I can share a repro based on a working project:

git clone https://github.com/willcohen/wasmts
cd wasmts
mvn clean compile

###### Run 10 times - typically ~2 succeed, ~8 fail
for i in {1..10}; do
  native-image --tool:svm-wasm -cp "target/classes:target/lib/*" \
    net.willcohen.wasmts.API target/wasmts 2>&1 | grep -E "(Finished|Failed)"
done

Expected Behavior

A successful build!

Actual Behavior

My output this last run was:

Finished generating 'wasmts' in 30.9s.
Finished generating 'wasmts' in 27.4s.
Failed generating 'wasmts' after 6.6s.
Finished generating 'wasmts' in 26.7s.
Failed generating 'wasmts' after 8.0s.
Failed generating 'wasmts' after 7.1s.
Failed generating 'wasmts' after 8.8s.
Finished generating 'wasmts' in 31.5s.
Failed generating 'wasmts' after 9.3s.
Failed generating 'wasmts' after 9.5s.

Steps to Reproduce

git clone https://github.com/willcohen/wasmts cd wasmts mvn clean compile

######## Run 10 times - typically ~2 succeed, ~8 fail for i in {1..10}; do native-image --tool:svm-wasm -cp "target/classes:target/lib/*"
net.willcohen.wasmts.API target/wasmts 2>&1 | grep -E "(Finished|Failed)" done

Additional Context

No response

Build Log Output and Error Messages

To see the stack trace

mvn package
native-image --tool:svm-wasm \
  -cp "target/classes:target/lib/jts-core-1.20.0.jar:target/lib/webimage-preview-25.0.0.jar" \
  net.willcohen.wasmts.API target/wasmts \
  -H:+ReportExceptionStackTraces 2>&1

===================================================================================================
GraalVM Native Image: Generating 'wasmts' (executable)...
===================================================================================================
[1/8] Initializing...                                                               (3.8s @ 0.12GB)
 Builder configuration:
 - Java version: 26+13, vendor version: Oracle GraalVM 26-dev+13.1
 - Graal compiler: optimization level: 2, target machine: unknown, PGO: off
 - C compiler: cc (apple, arm64, 17.0.0)
 - Assertions: disabled, system assertions: disabled
 - 1 user-specific feature(s):
   - com.oracle.svm.thirdparty.gson.GsonFeature
 Image configuration:
 - Garbage collector: JS-runtime-provided GC (max heap size: unknown)
 - Assertions: disabled (class-specific config may apply), system assertions: disabled
---------------------------------------------------------------------------------------------------
Build resources:
 - 11.03GiB of memory (45.9% of system memory, using all available memory)
 - 8 thread(s) (100.0% of 8 available processor(s), determined at start)
[2/8] Performing analysis...  []                                                    (1.5s @ 0.21GB)
    1,048 types,     555 fields, and   2,370 methods found reachable
      415 types,       7 fields, and     106 methods registered for reflection
        9 resource accesses registered with 0B total size

Error: Should not reach here: This method should never be called.
Internal exception: com.oracle.graal.pointsto.util.AnalysisError: Should not reach here: This method should never be called.
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.AnalysisError.shouldNotReachHere(AnalysisError.java:181)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.PrimitiveTypeState.shouldNotReachHere(PrimitiveTypeState.java:171)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.PrimitiveTypeState.objectsIterator(PrimitiveTypeState.java:157)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.TypeState.lambda$objects$0(TypeState.java:76)
        at org.graalvm.extraimage.builder/com.oracle.svm.hosted.webimage.pointsto.flow.InterceptJSInvokeTypeFlow.onObservedUpdate(InterceptJSInvokeTypeFlow.java:88)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.TypeFlow.lambda$addObserver$0(TypeFlow.java:748)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.executeCommand(CompletionExecutor.java:166)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.lambda$executeService$0(CompletionExecutor.java:152)
        at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute(ForkJoinTask.java:1750)
        at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute(ForkJoinTask.java:1742)
        at java.base/java.util.concurrent.ForkJoinTask$InterruptibleTask.exec(ForkJoinTask.java:1659)
        at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511)
        at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450)
        at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019)
        at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187)
Error: Should not reach here: This method should never be called.
Internal exception: com.oracle.graal.pointsto.util.AnalysisError: Should not reach here: This method should never be called.
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.AnalysisError.shouldNotReachHere(AnalysisError.java:181)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.PrimitiveTypeState.shouldNotReachHere(PrimitiveTypeState.java:171)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.PrimitiveTypeState.objectsIterator(PrimitiveTypeState.java:157)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.TypeState.lambda$objects$0(TypeState.java:76)
        at org.graalvm.extraimage.builder/com.oracle.svm.hosted.webimage.pointsto.flow.InterceptJSInvokeTypeFlow.onObservedUpdate(InterceptJSInvokeTypeFlow.java:88)
        at org.graalvm.extraimage.builder/com.oracle.svm.hosted.webimage.pointsto.flow.InterceptJSInvokeTypeFlow.lambda$onFlowEnabled$0(InterceptJSInvokeTypeFlow.java:78)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.AbstractAnalysisEngine$1.run(AbstractAnalysisEngine.java:337)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.executeCommand(CompletionExecutor.java:166)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.lambda$executeService$0(CompletionExecutor.java:152)
        at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute(ForkJoinTask.java:1750)
        at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute(ForkJoinTask.java:1742)
        at java.base/java.util.concurrent.ForkJoinTask$InterruptibleTask.exec(ForkJoinTask.java:1659)
        at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511)
        at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450)
        at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019)
        at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187)
---------------------------------------------------------------------------------------------------
             0.3s (4.3% of total time) in 16 GCs | Peak RSS: 904.15MB | CPU load: 3.96
===================================================================================================
Failed generating 'wasmts' after 5.4s.

willcohen avatar Dec 08 '25 17:12 willcohen

Thanks for reporting, will look into it. This looks like a small oversight on our side that only gets triggered if the static analysis runs in a specific order.

patrick96 avatar Dec 08 '25 18:12 patrick96

You got it, and thanks a bunch. Possible fix at #12677.

willcohen avatar Dec 08 '25 19:12 willcohen

I still don’t have a small repro but after spending the last few hours doing a large number of rebuilds using the branch from the PR, the issue is resolved with it.

willcohen avatar Dec 08 '25 22:12 willcohen

Thanks for providing a fix. I have debugged this on my end and while your solution indeed solves this issue, these primitive states should never even appear in InterceptJSInvokeTypeFlow. I have a fix for the root cause that seems to work, your reproducer has been running successfully in a loop now for over half an hour.

I will let you know once my fix is mirrored to GitHub so that you can try it out

patrick96 avatar Dec 12 '25 16:12 patrick96

Lovely. Many thanks!

willcohen avatar Dec 12 '25 16:12 willcohen

Please try out the fix #12707

patrick96 avatar Dec 12 '25 17:12 patrick96