{"record":{"id":"f7a529280d1c6c8a","repo":"oracle/graal","slug":"failed-to-serialize-op-due-to-cause","errorCode":null,"errorMessage":"Failed to serialize ${op} due to: ${cause}","messagePattern":"Failed to serialize (.+?) due to: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/JsonReplayCodec.java","lineNumber":202,"sourceCode":"            return TAG;\n        }\n\n        @Override\n        public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException {\n            OperationRecorder.RecordedOperation op = (OperationRecorder.RecordedOperation) instance;\n            try {\n                serializer.serialize(op.receiver(), objectBuilder.append(\"recv\"));\n                objectBuilder.append(\"method\", Arrays.asList(op.method().methodAndParamNames()));\n                if (op.args() != null) {\n                    try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append(\"args\").array()) {\n                        for (Object arg : op.args()) {\n                            serializer.serialize(arg, arrayBuilder.nextEntry());\n                        }\n                    }\n                }\n                serializer.serialize(op.resultOrMarker(), objectBuilder.append(\"res\"));\n            } catch (IllegalArgumentException e) {\n                throw new IllegalArgumentException(\"Failed to serialize \" + op + \" due to: \" + e.getMessage(), e);\n            }\n        }\n\n        @SuppressWarnings(\"unchecked\")\n        @Override\n        public OperationRecorder.RecordedOperation deserialize(EconomicMap<String, Object> json, RecursiveDeserializer deserializer, CompilationProxies.ProxyFactory proxyFactory)\n                        throws DeserializationException {\n            Object recv = deserializer.deserialize(json.get(\"recv\"), proxyFactory);\n            List<Object> methodProp = (List<Object>) json.get(\"method\");\n            String[] methodArray = new String[methodProp.size()];\n            for (int i = 0; i < methodArray.length; i++) {\n                methodArray[i] = (String) methodProp.get(i);\n            }\n            CompilationProxy.SymbolicMethod method = new CompilationProxy.SymbolicMethod(methodArray);\n            List<Object> list = (List<Object>) json.get(\"args\");\n            Object[] args;\n            if (list == null) {\n                args = null;","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/JsonReplayCodec.java#L184-L220","documentation":"JsonReplayCodec's RecordedOperation serializer wraps a lower-level IllegalArgumentException that escaped while serializing the receiver, method name list, arguments, or result marker of a recorded operation. The message chains the original cause, so the real failure is in e.getMessage() and the cause chain; the operation itself (op.toString()) is included to identify which recorded call failed.","triggerScenarios":"Serializing a RecordedOperation whose receiver or argument object has no registered ObjectSerializer (propagates as IllegalArgumentException from RecursiveSerializer), or whose method()/args()/resultOrMarker() returns something the codec cannot encode.","commonSituations":"Recording a compilation that touches a compiler-interface type for which no serializer was registered (new JDK/Graal version adds a type); a recorded value being of an exotic class; serializing proxies created by a mismatched codec version.","solutions":["Read the chained cause ('due to: ...') — it names the actual unserializable value; register an ObjectSerializer for that class in JsonReplayCodec","Ensure recording and JSON serialization run on the same GraalVM/compiler build","If the type is incidental, avoid recording it (narrow the recorded compiler-interface surface)","Add a serializer analogous to the existing ones (clazz()/tag()/serialize/deserialize) and register it in the codec's serializer table"],"exampleFix":"// before: no serializer for new type X -> 'Failed to serialize op ... due to: No serializer for class X'\n// after: register one\n// tagSerializers.put(\"x\", new ObjectSerializer() {\n//     public Class<?> clazz() { return X.class; }\n//     public String tag() { return \"x\"; }\n//     public void serialize(Object i, JsonBuilder.ObjectBuilder b, RecursiveSerializer s) throws IOException { ... }\n//     public Object deserialize(EconomicMap<String,Object> j, RecursiveDeserializer d, CompilationProxies.ProxyFactory p) { ... }\n// });","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    codec.write(compilationUnit, writer);\n} catch (IllegalArgumentException e) {\n    Throwable root = getRootCause(e); // walk e.getCause() chain\n    // root names the actual unserializable value; report it, do not retry blindly\n    throw new ReplaySerializationException(\"op failed: \" + e.getMessage(), root);\n}","preventionTips":["Run recording and JSON serialization in the same JVM/build so serializer coverage matches recorded types","When adding compiler-interface methods, add serializers for new parameter types in the same change","Log the recorded operation type when serialization fails to speed up serializer gaps diagnosis"],"tags":["graalvm","replay","serialization","json"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}