{"record":{"id":"ca0cf2b4a383c056","repo":"alibaba/spring-ai-alibaba","slug":"failed-to-serialize-metadata-record","errorCode":null,"errorMessage":"Failed to serialize metadata record {}","messagePattern":"Failed to serialize metadata record (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/serializer/plain_text/jackson/SerializationHelper.java","lineNumber":213,"sourceCode":"\t\t\t\t\tif (shouldInclude(provider, propertyInclusion, property, propertyValue)) {\n\t\t\t\t\t\tboolean hasAssignedSerializer = propertyWriter.isUnwrapping()\n\t\t\t\t\t\t\t\t|| !propertyWriter.getName().equals(property.getName())\n\t\t\t\t\t\t\t\t|| propertyWriter.getTypeSerializer() != null\n\t\t\t\t\t\t\t\t|| (propertyValue == null\n\t\t\t\t\t\t\t\t\t\t? propertyWriter.hasNullSerializer()\n\t\t\t\t\t\t\t\t\t\t: propertyWriter.hasSerializer());\n\t\t\t\t\t\tif (hasAssignedSerializer) {\n\t\t\t\t\t\t\tnormalized.putAll(applyPropertyWriter(provider, propertyWriter, record));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tnormalized.put(property.getName(),\n\t\t\t\t\t\t\t\t\tnormalizeMetadataValue(provider, propertyValue,\n\t\t\t\t\t\t\t\t\t\t\tpropertyInclusion.getContentInclusion()));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch (IllegalArgumentException ex) {\n\t\t\t\t\tthrow new IOException(\"Failed to serialize metadata record \" + record.getClass().getName(), ex);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (BeanPropertyWriter propertyWriter : remainingWriters) {\n\t\t\t\tnormalized.putAll(applyPropertyWriter(provider, propertyWriter, record));\n\t\t\t}\n\t\t\treturn normalized;\n\t\t}\n\t\treturn value;\n\t}\n\n\tprivate static boolean requiresRecordNormalization(SerializerProvider provider, Record record,\n\t\t\tList<BeanPropertyDefinition> properties) throws IOException {\n\t\tfor (BeanPropertyDefinition property : properties) {\n\t\t\tAnnotatedMember accessor = property.getAccessor();\n\t\t\tif (accessor == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttry {","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/serializer/plain_text/jackson/SerializationHelper.java#L195-L231","documentation":"While normalizing a Java record used as a metadata value, SerializationHelper invokes Jackson property accessors/serializers and catches IllegalArgumentException. When record property access throws (e.g. a compact constructor or accessor invariant is violated, or a value fails Jackson coercion), it is rethrown as IOException naming the record class.","triggerScenarios":"normalizeMetadataValue -> record property normalization: calling a record accessor or Jackson's serialization of a property raised IllegalArgumentException — e.g. accessor validates and rejects its stored state, or an incompatible nested container value.","commonSituations":"Records with validating compact constructors whose fields were deserialized/modified inconsistently; metadata values containing types Jackson cannot serialize with the configured ObjectMapper (unregistered modules, unsupported containers).","solutions":["Inspect the nested IllegalArgumentException cause to find which record property fails and fix the value before storing it in metadata","Ensure all record components are of Jackson-serializable types (register JavaTimeModule etc. for dates, optionals)","Make record accessors side-effect-free validation — validate in the compact constructor instead of failing during access","Replace the problematic metadata value with a plain POJO/Map if the type keeps failing normalization"],"exampleFix":"// before: accessor throws on bad state\npublic record Range(int lo, int hi) { public int lo() { if (lo > hi) throw new IllegalArgumentException(); return lo; } }\n// after: validate once in the compact constructor\npublic record Range(int lo, int hi) { public Range { if (lo > hi) throw new IllegalArgumentException(\"lo>hi\"); } }","handlingStrategy":"try-catch","validationCode":"try { for (var c : record.getClass().getRecordComponents()) c.getAccessor().invoke(value); } catch (Exception e) { /* exclude this value from metadata */ }","typeGuard":"boolean isMetadataSafe(Object v) {\n    return v == null || v instanceof String || v instanceof Number || v instanceof Boolean || v instanceof Map || isSafelySerializableRecord(v);\n}","tryCatchPattern":"try { metadata.put(key, recordValue); } catch (IOException e) { if (e.getMessage().startsWith(\"Failed to serialize metadata record\")) { metadata.put(key, String.valueOf(recordValue)); } else throw e; }","preventionTips":["Keep record accessors free of throwing validation; validate in compact constructors","Only store Jackson-serializable types in graph metadata","Register all needed Jackson modules on the shared ObjectMapper"],"tags":["serialization","jackson","records"],"backgroundTag":"json-marshal-failed","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}