{"record":{"id":"6d8bbe69d86d6215","repo":"alibaba/spring-ai-alibaba","slug":"bytes-cannot-be-empty-6d8bbe","errorCode":null,"errorMessage":"bytes cannot be empty","messagePattern":"bytes cannot be empty","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/serializer/StateSerializer.java","lineNumber":80,"sourceCode":"\n\tpublic abstract void writeData(Map<String, Object> data, ObjectOutput out) throws IOException;\n\n\tpublic abstract Map<String, Object> readData(ObjectInput in) throws IOException, ClassNotFoundException;\n\n\tpublic final byte[] dataToBytes(Map<String, Object> data) throws IOException {\n\t\tObjects.requireNonNull(data, \"object cannot be null\");\n\t\ttry (ByteArrayOutputStream stream = new ByteArrayOutputStream()) {\n\t\t\tObjectOutputStream oas = new ObjectOutputStream(stream);\n\t\t\twriteData(data, oas);\n\t\t\toas.flush();\n\t\t\treturn stream.toByteArray();\n\t\t}\n\t}\n\n\tpublic final Map<String, Object> dataFromBytes(byte[] bytes) throws IOException, ClassNotFoundException {\n\t\tObjects.requireNonNull(bytes, \"bytes cannot be null\");\n\t\tif (bytes.length == 0) {\n\t\t\tthrow new IllegalArgumentException(\"bytes cannot be empty\");\n\t\t}\n\t\ttry (ByteArrayInputStream stream = new ByteArrayInputStream(bytes)) {\n\t\t\tObjectInputStream ois = new ObjectInputStream(stream);\n\t\t\treturn readData(ois);\n\t\t}\n\t}\n\n}\n","sourceCodeStart":62,"sourceCodeEnd":89,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/serializer/StateSerializer.java#L62-L89","documentation":"StateSerializer.dataFromBytes performs the same validation as Serializer.bytesToObject: null bytes throw NullPointerException, and a zero-length array throws IllegalArgumentException(\"bytes cannot be empty\"), because ObjectInputStream cannot read state data from an empty stream.","triggerScenarios":"Calling dataFromBytes (or deserialized()) with an empty byte[] produced by a failed/empty save — e.g. an empty checkpoint blob loaded from Redis/PostgreSQL/file, or a serialization step that silently wrote nothing.","commonSituations":"Empty Redis keys storing empty arrays; interrupted checkpoint writes; schema/migration issues leaving state columns empty.","solutions":["Validate the byte array (length > 0) before deserializing state","Re-run the checkpoint save path and confirm bytes are non-empty on write","Purge corrupt/empty checkpoints so the graph starts from a fresh state","Add a round-trip unit test for your StateSerializer to catch empty-payload writes"],"exampleFix":"// before\nMap<String,Object> state = serializer.dataFromBytes(raw);\n// after\nMap<String,Object> state = (raw == null || raw.length == 0)\n    ? Map.of()\n    : serializer.dataFromBytes(raw);","handlingStrategy":"validation","validationCode":"if (bytes == null || bytes.length == 0) {\n    return Map.of(); // or re-initialize default graph state\n}","typeGuard":"boolean hasStateBytes(byte[] b) {\n    return b != null && b.length > 0;\n}","tryCatchPattern":"try {\n    return serializer.dataFromBytes(bytes);\n} catch (IllegalArgumentException e) {\n    if (\"bytes cannot be empty\".equals(e.getMessage())) {\n        return new HashMap<>(); // start from empty state\n    }\n    throw e;\n}","preventionTips":["Verify checkpoint writes persist non-empty bytes (assert on read-back)","Handle empty Redis/DB values as 'no saved state', not a fatal error","Test interruption during checkpoint save","Use checksums on stored state to detect corrupt/empty payloads"],"tags":["deserialization","state-serializer","empty-input","checkpoint"],"backgroundTag":"empty-required-field","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"}