{"record":{"id":"a2452c17303fa31b","repo":"oracle/graal","slug":"no-serializer-for-instanceclass-instance","errorCode":null,"errorMessage":"No serializer for ${instanceClass}: ${instance}","messagePattern":"No serializer for (.+?): (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/JsonReplayCodec.java","lineNumber":1900,"sourceCode":"    private final RecursiveSerializer recursiveSerializer = new RecursiveSerializer() {\n        @Override\n        public void serialize(Object instance, JsonBuilder.ValueBuilder valueBuilder) throws IOException {\n            if (instance == null) {\n                valueBuilder.value(null);\n                return;\n            }\n            ObjectSerializer serializer = exactClassSerializers.get(instance.getClass());\n            if (serializer == null) {\n                var cursor = interfaceSerializers.getEntries();\n                while (cursor.advance()) {\n                    if (cursor.getKey().isInstance(instance)) {\n                        serializer = cursor.getValue();\n                        exactClassSerializers.put(instance.getClass(), serializer);\n                        break;\n                    }\n                }\n                if (serializer == null) {\n                    throw new IllegalArgumentException(\"No serializer for \" + instance.getClass() + \": \" + instance);\n                }\n            }\n            try (JsonBuilder.ObjectBuilder builder = valueBuilder.object()) {\n                builder.append(\"tag\", serializer.tag());\n                serializer.serialize(instance, builder, this);\n            }\n        }\n\n        @Override\n        public void serialize(Object instance, JsonBuilder.ValueBuilder valueBuilder, String tag) throws IOException {\n            if (instance == null) {\n                valueBuilder.value(null);\n                return;\n            }\n            ObjectSerializer serializer = tagSerializers.get(tag);\n            if (serializer == null) {\n                throw new IllegalArgumentException(\"No serializer registered for the given tag \" + tag);\n            }","sourceCodeStart":1882,"sourceCodeEnd":1918,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/JsonReplayCodec.java#L1882-L1918","documentation":"RecursiveSerializer.serialize(Object, ValueBuilder) dispatches by looking up an ObjectSerializer: first an exact-class map, then a scan of interface-keyed serializers (with result caching into the exact-class map). If neither finds a handler, it throws IllegalArgumentException naming the class and instance — the recorded object graph contains a type the codec was never taught to serialize.","triggerScenarios":"Any recorded value whose class implements none of the registered serializer classes/interfaces — typically a new JDK/Graal type introduced by version drift, or an object reaching the recorder through a custom compiler-interface method.","commonSituations":"Upgrading one side (recorder or serializer) of a replay workflow without the other; custom compiler-interface extensions recording domain objects; unexpected java.* types (Class, MethodHandles, lambdas) leaking into recorded results.","solutions":["Take the class name from the message and register an ObjectSerializer (clazz/tag/serialize/deserialize) for it in JsonReplayCodec","If it is a JDK type, serialize it structurally (e.g. by name string) rather than by proxy","Re-record and serialize with the same GraalVM build so the type sets match","Filter the offending value out of recording if it is not needed for replay"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    serializer.serialize(value, valueBuilder);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"No serializer for\")) {\n        // log class name, skip or structurally encode the value; do not corrupt the stream silently\n        LOG.warning(\"Unhandled replay type: \" + e.getMessage());\n    } else { throw e; }\n}","preventionTips":["Keep serializer coverage in lockstep with the recorded compiler interface: one change adds the type and its serializer","Add a canSerialize(Object) probe API in forks to assert coverage before a long recording run","Run a smoke serialize right after recording so gaps fail fast, not at replay time"],"tags":["graalvm","replay","serialization","codec"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}