{"record":{"id":"e7d3a886147aa931","repo":"spring-projects/spring-ai","slug":"failed-to-serialize","errorCode":null,"errorMessage":"Failed to serialize","messagePattern":"Failed to serialize","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-ai-commons/src/main/java/org/springframework/ai/document/id/JdkSha256HexIdGenerator.java","lineNumber":84,"sourceCode":"\t\tbyte[] hashBytes = getMessageDigest().digest(contentWithMetadata);\n\t\tStringBuilder sb = new StringBuilder();\n\t\tfor (byte b : hashBytes) {\n\t\t\tsb.append(String.format(this.byteHexFormat, b));\n\t\t}\n\t\treturn UUID.nameUUIDFromBytes(sb.toString().getBytes(this.charset)).toString();\n\t}\n\n\tprivate byte[] serializeToBytes(Object... contents) {\n\t\tAssert.notNull(contents, \"Contents must not be null\");\n\t\ttry (ByteArrayOutputStream byteOut = new ByteArrayOutputStream()) {\n\t\t\tObjectOutputStream out = new ObjectOutputStream(byteOut);\n\t\t\tfor (Object content : contents) {\n\t\t\t\tout.writeObject(content);\n\t\t\t}\n\t\t\treturn byteOut.toByteArray();\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new RuntimeException(\"Failed to serialize\", e);\n\t\t}\n\t}\n\n\tMessageDigest getMessageDigest() {\n\t\ttry {\n\t\t\treturn (MessageDigest) this.messageDigest.clone();\n\t\t}\n\t\tcatch (CloneNotSupportedException e) {\n\t\t\tthrow new RuntimeException(\"Unsupported clone for MessageDigest.\", e);\n\t\t}\n\t}\n\n}\n","sourceCodeStart":66,"sourceCodeEnd":98,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/spring-ai-commons/src/main/java/org/springframework/ai/document/id/JdkSha256HexIdGenerator.java#L66-L98","documentation":"serializeToBytes() serializes id-content objects with Java ObjectOutputStream to hash them; any failure (NotSerializableException, IOException on the internal ByteArrayOutputStream) is wrapped in RuntimeException('Failed to serialize'). Since ByteArrayOutputStream can't actually throw IOException, real failures are almost always non-serializable content passed to generate().","triggerScenarios":"Calling jdkSha256HexIdGenerator.generate(obj) where obj (or a nested field) does not implement java.io.Serializable, e.g. a Document whose metadata holds a lambda, streams, or third-party non-serializable types.","commonSituations":"Hashing documents with metadata maps containing ObjectMapper instances, InputStreams, or lambdas captured from method references.","solutions":["Ensure every object passed to generate() is fully Serializable (including nested values)","Convert content to a String/byte[] yourself and hash deterministically instead of relying on Java serialization","Inspect the wrapped cause (NotSerializableException names the offending class)","Use a different IdGenerator (e.g. RandomIdGenerator) if content isn't serializable"],"exampleFix":"// before\nString id = idGenerator.generate(document.getMetadata()); // metadata holds non-serializable values\n// after\nString id = idGenerator.generate(String.valueOf(document.getMetadata())); // plain String, always serializable","handlingStrategy":"validation","validationCode":"// ensure content is serializable before hashing\nif (!(content instanceof java.io.Serializable)) {\n    content = String.valueOf(content);\n}","typeGuard":"static Object requireSerializable(Object o) {\n    return o instanceof java.io.Serializable ? o : String.valueOf(o);\n}","tryCatchPattern":"try {\n    id = gen.generate(content);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Failed to serialize\")) {\n        id = gen.generate(String.valueOf(content));\n    } else throw e;\n}","preventionTips":["Only pass Serializable content (Strings, numbers, serializable POJOs)","Avoid lambdas, streams, and framework objects in hashed content","Check the wrapped NotSerializableException cause to find offending fields"],"tags":["serialization","hashing","id-generation"],"backgroundTag":"json-marshal-failed","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}