{"record":{"id":"4dad823cf20584ae","repo":"oracle/graal","slug":"constant-has-unexpected-type","errorCode":null,"errorMessage":"Constant has unexpected type {}: {}","messagePattern":"Constant has unexpected type (.+?): (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalResolvedJavaModule.java","lineNumber":44,"sourceCode":"\nimport java.util.Objects;\nimport java.util.Set;\n\nimport org.graalvm.polyglot.TypeLiteral;\nimport org.graalvm.polyglot.Value;\n\nimport jdk.graal.compiler.vmaccess.ResolvedJavaModule;\nimport jdk.graal.compiler.vmaccess.ResolvedJavaModuleLayer;\n\nfinal class EspressoExternalResolvedJavaModule implements ResolvedJavaModule {\n    private final EspressoExternalVMAccess access;\n    private final String name;\n    final Value moduleValue;\n\n    EspressoExternalResolvedJavaModule(EspressoExternalVMAccess access, Value moduleValue) {\n        // j.l.Module?\n        if (!\"java.lang.Module\".equals(moduleValue.getMetaObject().getMetaQualifiedName())) {\n            throw new IllegalArgumentException(\"Constant has unexpected type \" + moduleValue.getMetaObject().getMetaQualifiedName() + \": \" + moduleValue);\n        }\n        this.access = access;\n        this.moduleValue = moduleValue;\n        this.name = access.java_lang_Module_getName.getMirror().execute(moduleValue).asString();\n    }\n\n    @Override\n    public ResolvedJavaModuleLayer getLayer() {\n        Value layer = moduleValue.invokeMember(\"getLayer\");\n        return layer.isNull() ? null : new EspressoExternalResolvedJavaModuleLayer(access, layer);\n    }\n\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @Override","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalResolvedJavaModule.java#L26-L62","documentation":"Thrown by the EspressoExternalResolvedJavaModule constructor when the polyglot Value passed in is not an instance of guest java.lang.Module (checked via getMetaObject().getMetaQualifiedName()). The adapter dereferences the Value's meta-object immediately and builds a ResolvedJavaModule wrapper around it, so a Value of any other guest type (Class, ModuleLayer, String, null-meta foreign object) fails construction. This guards the boundary where arbitrary interop Values enter the JVMCI type system.","triggerScenarios":"Calling whatever API produced this wrapper (module lookup in EspressoExternalVMAccess) with a Value obtained from a Class.getModule() on a primitive/array class, a ModuleLayer Value, or a host object mapped with asValue(...) that has a host meta-object with a different qualified name.","commonSituations":"Module-aware lookups over classes loaded by the bootstrap loader (unnamed module handling), polyglot context configuration where host meta-objects differ from guest ones, and version changes in how the access layer resolves modules.","solutions":["Check value.getMetaObject().getMetaQualifiedName().equals(\"java.lang.Module\") before constructing/looking up the module","Handle null meta-object (foreign/host Values) by mapping the object into the Espresso guest context first","If the Value came from getLayer()/ModuleLayer APIs, unwrap the actual module members instead of passing the layer"],"exampleFix":"// before\nResolvedJavaModule m = access.findModule(someValue);\n\n// after\nif (someValue.getMetaObject() == null ||\n    !\"java.lang.Module\".equals(someValue.getMetaObject().getMetaQualifiedName())) {\n    throw new IllegalArgumentException(\"not a guest java.lang.Module: \" + someValue);\n}\nResolvedJavaModule m = access.findModule(someValue);","handlingStrategy":"type-guard","validationCode":"Value meta = moduleValue.getMetaObject();\nif (meta == null || !\"java.lang.Module\".equals(meta.getMetaQualifiedName())) {\n    throw new IllegalArgumentException(\"not a guest java.lang.Module: \" + moduleValue);\n}","typeGuard":"boolean isGuestModule(Value v) {\n    Value meta = v.getMetaObject();\n    return meta != null && \"java.lang.Module\".equals(meta.getMetaQualifiedName());\n}","tryCatchPattern":null,"preventionTips":["Validate the meta-object qualified name before passing any Value into module lookups","Handle null meta-objects (foreign/host Values) by mapping into the Espresso guest context first","Do not feed ModuleLayer Values or Class Values where a Module is expected"],"tags":["espresso","jvmci","module","polyglot","type-check"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}