{"record":{"id":"09be9d13418cc2df","repo":"oracle/graal","slug":"failed-to-find-a-class-object-for-s-this-can-be","errorCode":null,"errorMessage":"Failed to find a Class object for %s. This can be fixed by adding %s.class to ReplayTypeSupport#KNOWN_CLASSES.","messagePattern":"Failed to find a Class object for (.+?)\\. This can be fixed by adding (.+?)\\.class to ReplayTypeSupport#KNOWN_CLASSES\\.","errorType":"exception","errorClass":"GraalError","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayTypeSupport.java","lineNumber":141,"sourceCode":"            return primitiveClass;\n        }\n        Class<?> knownClass = KNOWN_CLASSES.get(name);\n        if (knownClass != null) {\n            return knownClass;\n        }\n        return new ClassSurrogate(name);\n    }\n\n    /**\n     * Casts a deserialized object to a {@link Class}.\n     *\n     * @param clazz the deserialized class object or surrogate\n     * @return the class object cast to the requested type\n     */\n    @SuppressWarnings(\"unchecked\")\n    static <C> Class<C> classCast(Object clazz) {\n        if (clazz instanceof ClassSurrogate(String name)) {\n            throw new GraalError(String.format(\"Failed to find a Class object for %s. This can be fixed by adding %s.class to ReplayTypeSupport#KNOWN_CLASSES.\", name, name));\n        }\n        return (Class<C>) clazz;\n    }\n\n    /**\n     * Determines the enum element type that should be recorded for an {@link EnumSet}.\n     *\n     * @param enumSet the enum set whose element type should be determined\n     * @return the element type to serialize for the enum set\n     */\n    static Class<?> enumSetElementType(EnumSet<?> enumSet) {\n        Optional<?> maybeElementType = enumSet.stream().findAny();\n        if (maybeElementType.isPresent()) {\n            return ((Enum<?>) maybeElementType.get()).getDeclaringClass();\n        }\n        maybeElementType = EnumSet.complementOf(enumSet).stream().findAny();\n        if (maybeElementType.isPresent()) {\n            return ((Enum<?>) maybeElementType.get()).getDeclaringClass();","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayTypeSupport.java#L123-L159","documentation":"Thrown by ReplayTypeSupport.classCast during replay deserialization when a replay file references a Class whose name is not in the KNOWN_CLASSES table, so it was decoded as a ClassSurrogate placeholder. When the codec actually needs a real Class object (not just name-based matching), the surrogate cannot be cast and GraalError tells you to extend KNOWN_CLASSES.","triggerScenarios":"Replaying a recorded compilation whose data contains a Class constant not listed in ReplayTypeSupport.KNOWN_CLASSES (table built in createKnownClasses: CPUFeature enums, JavaKind, HotSpotResolved* types, etc.). decodeClass returns a ClassSurrogate, and a later classCast of that surrogate throws. The check is skipped inside libgraal (image) builds; it fires in non-image runtimes.","commonSituations":"A new kind of Class constant starts flowing through the compiler interface between the recording and replaying builds (e.g. a new VM-CI meta type or arch feature enum); recording and replaying with different GraalVM versions; adding a new field of type Class to a recorded compiler-interface object.","solutions":["Add the missing class (e.g. MyType.class) to the KNOWN_CLASSES array in ReplayTypeSupport.createKnownClasses and rebuild.","Regenerate the replay file with a build whose KNOWN_CLASSES covers the classes the compilation actually touches.","Ensure recording and replay run on the same GraalVM/compiler version so the class set matches."],"exampleFix":"// before\nClass<?>[] classes = { JavaKind.class, ResolvedJavaMethod.class, /* ... */ };\n\n// after\nClass<?>[] classes = { JavaKind.class, ResolvedJavaMethod.class,\n                jdk.vm.ci.meta.MyNewType.class, /* ... */ };","handlingStrategy":"validation","validationCode":null,"typeGuard":"// detect a surrogate before casting\nObject decoded = ReplayTypeSupport.decodeClass(name);\nif (decoded.getClass().getSimpleName().equals(\"ClassSurrogate\")) {\n    // class not in KNOWN_CLASSES: add it before replay will work\n}","tryCatchPattern":"try {\n    Class<?> c = ReplayTypeSupport.classCast(decoded);\n} catch (GraalError e) {\n    if (e.getMessage().contains(\"KNOWN_CLASSES\")) {\n        // extract the class name and add it to ReplayTypeSupport.KNOWN_CLASSES\n    }\n    throw e;\n}","preventionTips":["Record and replay with the same GraalVM build so KNOWN_CLASSES covers the class set.","When adding a Class-typed field to a recorded compiler-interface object, add the class to KNOWN_CLASSES in the same change."],"tags":["graalvm","replay-compilation","deserialization","class-resolution"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}