{"record":{"id":"60be653113e24ecc","repo":"oracle/graal","slug":"no-classconstant-at-constant-pool-index-cpi","errorCode":null,"errorMessage":"No ClassConstant at constant pool index ${cpi}","messagePattern":"No ClassConstant at constant pool index (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java","lineNumber":1916,"sourceCode":"    }\n\n    @Override\n    public final boolean isMagicAccessor() {\n        if (getJavaVersion().java23OrEarlier()) {\n            assert getMeta().sun_reflect_MagicAccessorImpl != null;\n            return getMeta().sun_reflect_MagicAccessorImpl.isAssignableFrom(this);\n        }\n        return false;\n    }\n\n    @Override\n    @TruffleBoundary\n    public final Klass resolveClassConstantInPool(int cpi) {\n        if (this instanceof ObjectKlass objectKlass) {\n            try {\n                return objectKlass.getConstantPool().resolvedKlassAt(objectKlass, cpi, false);\n            } catch (ClassCastException | IndexOutOfBoundsException e) {\n                throw new IllegalArgumentException(\"No ClassConstant at constant pool index \" + cpi);\n            }\n        }\n        return null;\n    }\n\n    @Override\n    public Method lookupVTableEntry(int vtableIndex) {\n        ObjectKlass k;\n        if (this instanceof ObjectKlass) {\n            k = (ObjectKlass) this;\n        } else if (this instanceof ArrayKlass) {\n            k = getMeta().java_lang_Object;\n        } else {\n            // primitive.\n            return null;\n        }\n        assert !k.isInterface();\n        Method.MethodVersion[] table = k.getVTable();","sourceCodeStart":1898,"sourceCodeEnd":1934,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java#L1898-L1934","documentation":"IllegalArgumentException from Klass.resolveClassConstantInPool: when resolving constant pool entry cpi as a CONSTANT_Class, the entry at that index is not a class constant (ClassCastException) or the index is outside the pool (IndexOutOfBoundsException). Both are converted to 'No ClassConstant at constant pool index <cpi>'.","triggerScenarios":"JVMCI/reflection-style API (resolveClassConstantInPool) invoked with a cpi that points to a String, MethodType, or other non-Class entry, or an index beyond pool length; bytecode instrumentation rewriting a class entry into a different tag without updating the caller.","commonSituations":"Tooling built on Espresso's Klass API (debuggers, hotswap, AOT scanners) that reads cp indices from one class version while the pool belongs to another; recompilation changing constant pool layout between the instrumentation pass and resolution.","solutions":["Validate the tag at cpi is CONSTANT_Class before resolving (Espresso's pool API exposes tag lookup).","Re-derive indices from the same class bytes that will be resolved — never cache cp indices across recompiles.","Bounds-check cpi against getConstantPool().length().","Catch IllegalArgumentException at the caller and fall back to a non-constant-pool resolution path if the index is untrusted."],"exampleFix":"// before\nKlass k = klass.resolveClassConstantInPool(cpi);\n\n// after\nif (cpi < 0 || cpi >= objectKlass.getConstantPool().length() ||\n                objectKlass.getConstantPool().tagAt(cpi) != ConstantTag.CLASS) {\n    throw new IllegalArgumentException(\"cpi \" + cpi + \" is not a class constant\");\n}\nKlass k = klass.resolveClassConstantInPool(cpi);","handlingStrategy":"validation","validationCode":"ConstantPool pool = objectKlass.getConstantPool();\nif (cpi < 0 || cpi >= pool.length() || pool.tagAt(cpi) != ConstantTag.CLASS) {\n    throw new IllegalArgumentException(\"cpi \" + cpi + \" is not a CONSTANT_Class entry\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    return klass.resolveClassConstantInPool(cpi);\n} catch (IllegalArgumentException e) {\n    // index not a class constant: re-derive cpi from current class bytes or fail gracefully\n}","preventionTips":["Never cache constant pool indices across class redefinitions/recompiles.","Check the tag at cpi equals CONSTANT_Class before resolving.","Bounds-check indices against pool length."],"tags":["constant-pool","class-loading","validation","espresso"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}