{"record":{"id":"bb3fae899234c9bc","repo":"oracle/graal","slug":"expected-an-espressoexternalobjectconstant-got-bb3fae","errorCode":null,"errorMessage":"Expected an EspressoExternalObjectConstant, got {}","messagePattern":"Expected an EspressoExternalObjectConstant, got (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalVMAccess.java","lineNumber":593,"sourceCode":"        return new EspressoExternalObjectConstant(this, array);\n    }\n\n    @Override\n    public JavaConstant createPrimitiveArray(JavaKind kind, int length) {\n        if (kind == null || !kind.isPrimitive() || kind == JavaKind.Void) {\n            throw new IllegalArgumentException(\"Expected a non-void primitive kind, got \" + kind);\n        }\n        if (length < 0) {\n            throw new NegativeArraySizeException(\"Negative array size: \" + length);\n        }\n        Value array = invokeJVMCIHelper(\"newPrimitiveArray\", (int) kind.getTypeChar(), 1, length);\n        return new EspressoExternalObjectConstant(this, array);\n    }\n\n    @Override\n    public JavaConstant clonePrimitiveArray(JavaConstant primitiveArray) {\n        if (!(primitiveArray instanceof EspressoExternalObjectConstant objectConstant)) {\n            throw new IllegalArgumentException(\"Expected an EspressoExternalObjectConstant, got \" + safeGetClass(primitiveArray));\n        }\n        EspressoResolvedObjectType arrayType = objectConstant.getType();\n        if (!(arrayType.isArray() && arrayType.getComponentType().isPrimitive())) {\n            throw new IllegalArgumentException(\"Expected a primitive array constant, got \" + arrayType);\n        }\n        Value copy = invokeJVMCIHelper(\"clonePrimitiveArray\", objectConstant.getValue());\n        return new EspressoExternalObjectConstant(this, copy);\n    }\n\n    @Override\n    public void copyArray(JavaConstant src, int srcPos, JavaConstant dest, int destPos, int length) {\n        if (!(src instanceof EspressoExternalObjectConstant srcArray)) {\n            throw new IllegalArgumentException(\"Expected an EspressoExternalObjectConstant for src, got \" + safeGetClass(src));\n        }\n        if (!(dest instanceof EspressoExternalObjectConstant destArray)) {\n            throw new IllegalArgumentException(\"Expected an EspressoExternalObjectConstant for dest, got \" + safeGetClass(dest));\n        }\n        if (!srcArray.getType().isArray()) {","sourceCodeStart":575,"sourceCodeEnd":611,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalVMAccess.java#L575-L611","documentation":"clonePrimitiveArray(primitiveArray) deep-copies a guest primitive array by unwrapping an EspressoExternalObjectConstant and calling the guest helper clonePrimitiveArray. A constant from any other JVMCI backend has no guest Value to clone, so it is rejected with IllegalArgumentException before the helper is invoked.","triggerScenarios":"Passing a host-created array constant (JavaConstant.forObject(byte[]) or HotSpot constant) or a constant from another Espresso context to clonePrimitiveArray.","commonSituations":"Copy-on-write snapshot logic that sometimes receives host arrays; caching constants across provider lifecycles; tests with hand-built constants.","solutions":["Only clone arrays originally created by this Espresso provider (createPrimitiveArray / asArrayConstant results).","Guard with primitiveArray instanceof EspressoExternalObjectConstant and use host-side clone() for host arrays.","Keep constants tagged with their originating provider in caches to avoid cross-provider leakage."],"exampleFix":"// before\nJavaConstant copy = vmAccess.clonePrimitiveArray(maybeHostConstant);\n\n// after\nJavaConstant copy = (maybeHostConstant instanceof EspressoExternalObjectConstant)\n        ? vmAccess.clonePrimitiveArray(maybeHostConstant)\n        : hostCopy(maybeHostConstant);","handlingStrategy":"type-guard","validationCode":"if (!(primitiveArray instanceof EspressoExternalObjectConstant)) {\n    // host array: clone on the host instead\n}","typeGuard":"static boolean isEspressoConstant(JavaConstant c) {\n    return c instanceof EspressoExternalObjectConstant;\n}","tryCatchPattern":"catch (IllegalArgumentException e) with 'Expected an EspressoExternalObjectConstant' -> clone host arrays with .clone(), guest arrays via the provider.","preventionTips":["Snapshot helpers should branch on constant origin before cloning.","Invalidate constant caches when a context is disposed.","Tag constants with their provider in wrappers you control."],"tags":["jvmci","espresso","graalvm","arrays","constants"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}