{"record":{"id":"f6e0293d2c9719bb","repo":"oracle/graal","slug":"hashcode-must-be-0","errorCode":null,"errorMessage":"hashcode must be > 0","messagePattern":"hashcode must be > 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalConstantReflectionProvider.java","lineNumber":351,"sourceCode":"            throw new IllegalArgumentException(\"Constant has unexpected type \" + constant.getClass() + \": \" + constant);\n        }\n        return objectConstant.guestHashCode();\n    }\n\n    @Override\n    public int makeIdentityHashCode(JavaConstant constant, int requestedValue) {\n        JavaKind kind = Objects.requireNonNull(constant).getJavaKind();\n        if (kind != JavaKind.Object) {\n            throw new IllegalArgumentException(\"Constant has unexpected kind \" + kind + \": \" + constant);\n        }\n        if (constant.isNull()) {\n            throw new NullPointerException();\n        }\n        if (!(constant instanceof EspressoExternalObjectConstant objectConstant)) {\n            throw new IllegalArgumentException(\"Constant has unexpected type \" + constant.getClass() + \": \" + constant);\n        }\n        if (requestedValue <= 0) {\n            throw new IllegalArgumentException(\"hashcode must be > 0\");\n        }\n        return access.invokeJVMCIHelper(\"makeIdentityHashCode\", objectConstant.getValue(), requestedValue).asInt();\n    }\n\n    @Override\n    public AbstractEspressoResolvedInstanceType getTypeForStaticBase(JavaConstant staticBase) {\n        if (!(staticBase instanceof EspressoExternalObjectConstant objectConstant)) {\n            return null;\n        }\n        Value type = access.invokeJVMCIHelper(\"getTypeForStaticBase\", objectConstant.getValue());\n        if (type.isNull()) {\n            return null;\n        }\n        return new EspressoExternalResolvedInstanceType(access, type);\n    }\n}\n","sourceCodeStart":333,"sourceCodeEnd":368,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalConstantReflectionProvider.java#L333-L368","documentation":"IllegalArgumentException from EspressoExternalConstantReflectionProvider.makeIdentityHashCode: the requested identity-hashcode value was <= 0. The JVM only ever assigns positive identity hashcodes, and the underlying VM helper (invokeJVMCIHelper(\"makeIdentityHashCode\", ...)) requires a positive value, so the reflection provider validates before crossing into the VM. This method is the JVMCI bridge behind IdentityHashCodes.set during continuation deserialization.","triggerScenarios":"Calling makeIdentityHashCode(constant, 0), with a negative value, or with a recorded hashcode that was decoded/sign-truncated to <= 0 (e.g. stored in a signed byte/short field somewhere in the persistence layer).","commonSituations":"Identity hashcodes persisted through a channel that cannot represent the full positive int range (ProtoBuf zigzag mishandling, JSON as signed int16); defaulting the 'requested value' parameter to 0 when no recording exists.","solutions":["Pass a strictly positive int; validate requestedValue > 0 at the call site before invoking the provider.","Fix the persistence encoding so recorded hashcodes round-trip as unsigned/positive 31-bit ints.","If no hashcode was recorded for the object, skip the call entirely instead of passing 0.","Check for integer sign-extension bugs when the recorded value traveled through smaller integer types."],"exampleFix":"// before\nprovider.makeIdentityHashCode(constant, (short) recordedHash); // sign-extended, can be <= 0\n\n// after\nif (recordedHash > 0) {\n    provider.makeIdentityHashCode(constant, recordedHash);\n} // else: no recorded hashcode, let the VM assign one","handlingStrategy":"validation","validationCode":"if (requestedValue <= 0) {\n    throw new IllegalArgumentException(\"requestedValue must be a positive int, got \" + requestedValue);\n}\nprovider.makeIdentityHashCode(constant, requestedValue);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate requestedValue > 0 before calling makeIdentityHashCode.","Skip the call when no hashcode was recorded instead of passing 0.","Encode persisted hashcodes so they round-trip as positive 31-bit ints (no sign truncation)."],"tags":["identity-hashcode","validation","jvmci","argument-validation"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}