{"record":{"id":"7c9509a4c0a671a9","repo":"oracle/graal","slug":"expected-an-espresso-object-constant-got","errorCode":null,"errorMessage":"Expected an espresso object constant, got {}","messagePattern":"Expected an espresso object constant, 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/EspressoExternalResolvedJavaField.java","lineNumber":145,"sourceCode":"            }\n            if (receiver.isNull()) {\n                throw new IllegalArgumentException(\"Receiver is null\");\n            }\n            if (!(receiver instanceof EspressoExternalObjectConstant espressoReceiver)) {\n                throw new IllegalArgumentException(\"Expected an espresso object receiver, got \" + receiver.getClass().getName());\n            }\n            receiverValue = espressoReceiver.getValue();\n        }\n\n        JavaKind kind = getJavaKind();\n        final Object boxed;\n        if (kind == JavaKind.Object) {\n            if (value.isNull()) {\n                boxed = null;\n            } else if (value instanceof EspressoExternalObjectConstant objConst) {\n                boxed = objConst.getValue();\n            } else {\n                throw new IllegalArgumentException(\"Expected an espresso object constant, got \" + value.getClass().getName());\n            }\n        } else {\n            if (kind != value.getJavaKind()) {\n                throw new IllegalArgumentException(\"Expected value kind \" + kind + \" but got \" + value.getJavaKind());\n            }\n            boxed = value.asBoxedPrimitive();\n        }\n\n        getAccess().invokeJVMCIHelper(\"writeField\", vmFieldMirror, receiverValue, boxed);\n    }\n\n    /**\n     * Gets a guest {@link java.lang.reflect.Field} value associated with this field, creating it\n     * first if necessary.\n     */\n    Value getReflectFieldMirror() {\n        Value value = reflectFieldMirror;\n        if (value == null) {","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalResolvedJavaField.java#L127-L163","documentation":"Thrown by EspressoExternalResolvedJavaField.writeValue when the field's JavaKind is Object but the value JavaConstant is neither null nor an EspressoExternalObjectConstant. For reference-typed fields the adapter can only forward a guest polyglot Value; the null constant is handled explicitly (boxed to null), so any other surviving constant class means the value originated outside the Espresso vmaccess layer and cannot be written into the guest object field. The message reports the actual constant class to identify the producer.","triggerScenarios":"Writing a reference field with a constant from another JVMCI backend (host ConstantReflectionProvider box methods, Vivify/HotSpot object constants, or a custom JavaConstant). Writing a boxed-primitive constant into an Object field is also rejected because EspressoExternalObjectConstant.asBoxedPrimitive itself throws.","commonSituations":"Compiler passes that reuse host constants for guest stores; test harnesses using JavaConstant.forObject(hostInstance); pipelines where the ConstantReflectionProvider is swapped per-context but cached constants leak across contexts.","solutions":["Create the value constant with the Espresso access layer so it is an EspressoExternalObjectConstant, or JavaConstant.NULL_POINTER when storing null","For host objects, convert to a guest Value (context.asValue(...)/polyglot embedding) and wrap via the Espresso constant reflection before the write","Audit caches keyed on JavaConstant for cross-backend contamination indicated by the class name in the message"],"exampleFix":"// before\nfield.writeValue(receiver, JavaConstant.forObject(hostString)); // foreign constant\n\n// after\nValue guestString = espressoAccess.invokeJVMCIHelper(\"toGuestString\", hostString);\nJavaConstant valueConst = espressoAccess.getConstantReflection().forObject(guestString);\nfield.writeValue(receiver, valueConst);","handlingStrategy":"validation","validationCode":"JavaKind fieldKind = field.getJavaKind();\nboolean ok = fieldKind != JavaKind.Object\n    ? value.getJavaKind() == fieldKind\n    : value.isNull() || value instanceof EspressoExternalObjectConstant;\nif (!ok) throw new IllegalStateException(\"value constant not usable for field \" + field.getName());","typeGuard":null,"tryCatchPattern":"catch (IllegalArgumentException e) { if (e.getMessage() != null && e.getMessage().startsWith(\"Expected an espresso object constant\")) { /* re-obtain constant from Espresso reflection */ } else throw e; }","preventionTips":["Never pass JavaConstant.forObject(hostObject) into guest field writes; convert the object to a guest Value first","Use JavaConstant.NULL_POINTER (isNull path) rather than foreign null wrappers when storing null","Centralize constant creation in one factory that talks only to the Espresso access layer"],"tags":["espresso","jvmci","type-mismatch","field-write","constant"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}