{"record":{"id":"023e03e160cc548e","repo":"alibaba/spring-ai-alibaba","slug":"unable-to-insert-checkpoint-023e03","errorCode":null,"errorMessage":"Unable to insert checkpoint","messagePattern":"Unable to insert checkpoint","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/mysql/MysqlSaver.java","lineNumber":504,"sourceCode":"\t\t\t\tupsertStatement.setString(1, UUID.randomUUID().toString());\n\t\t\t\tupsertStatement.setString(2, threadName);\n\t\t\t\tupsertStatement.execute();\n\n\t\t\t\tinsertCheckpointStatement.setString(1, checkpoint.getId());\n\t\t\t\tinsertCheckpointStatement.setString(2, checkpoint.getNodeId());\n\t\t\t\tinsertCheckpointStatement.setString(3, checkpoint.getNextNodeId());\n\t\t\t\tinsertCheckpointStatement.setString(4, encodeState(checkpoint.getState()));\n\t\t\t\tinsertCheckpointStatement.setString(5, threadName);\n\t\t\t\tinsertCheckpointStatement.execute();\n\t\t\t}\n\n\t\t\tconn.commit();\n\t\t\tlog.debug(\"Checkpoint {} for thread {} inserted successfully.\", checkpoint.getId(), threadName);\n\t\t}\n\t\tcatch (SQLException | IOException ex) {\n\t\t\tlog.error(\"Error inserting checkpoint with id {} in thread {}\", checkpoint.getId(), threadName, ex);\n\t\t\trollback(conn, checkpoint, threadName);\n\t\t\tthrow new Exception(\"Unable to insert checkpoint\", ex);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void updateCheckpoint(String threadName, String checkpointId, Checkpoint checkpoint) throws Exception {\n\t\tConnection conn = null;\n\t\ttry (Connection ignored = conn = dataSource.getConnection()) {\n\t\t\tconn.setAutoCommit(false);\n\n\t\t\ttry (PreparedStatement preparedStatement = conn.prepareStatement(UPDATE_CHECKPOINT)) {\n\t\t\t\tpreparedStatement.setString(1, checkpoint.getId());\n\t\t\t\tpreparedStatement.setString(2, checkpoint.getNodeId());\n\t\t\t\tpreparedStatement.setString(3, checkpoint.getNextNodeId());\n\t\t\t\tpreparedStatement.setString(4, encodeState(checkpoint.getState()));\n\t\t\t\tpreparedStatement.setString(5, threadName);\n\t\t\t\tpreparedStatement.setString(6, checkpointId);\n\t\t\t\tint rowsAffected = preparedStatement.executeUpdate();\n\t\t\t\tif (rowsAffected == 0) {","sourceCodeStart":486,"sourceCodeEnd":522,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/mysql/MysqlSaver.java#L486-L522","documentation":"MysqlSaver.insertCheckpoint() wraps SQLException or IOException raised while inserting a new checkpoint inside a transaction into an Exception with this message. Before throwing, the saver logs the error and rolls back the transaction, so a failed insert leaves no partial data.","triggerScenarios":"Saving a checkpoint after a graph step when: the INSERT fails (connection loss, constraint violation, table missing, wrong schema); or encoding the checkpoint state to the stored format throws IOException (non-serializable state object).","commonSituations":"Checkpoint table not created (schema init skipped); MySQL max_allowed_packet too small for large state blobs; non-serializable object placed in agent state; connection pool exhaustion or transient DB failover during a run.","solutions":["Check the logged underlying exception for the exact SQL error (table missing, packet too large, constraint).","Create/verify the checkpoint table schema matches the current MysqlSaver version.","Increase MySQL max_allowed_packet or reduce state size if the blob exceeds limits.","Make all objects stored in graph state Serializable; connection-pool issues: raise pool size / enable retry on transient errors."],"exampleFix":"// before\nMap<String, Object> state = Map.of(\"conn\", new Connection()); // not serializable -> IOException\n// after\nMap<String, Object> state = Map.of(\"connId\", connectionId); // store serializable data only","handlingStrategy":"retry","validationCode":"// ensure state values are serializable before saving\nfor (Object v : state.values()) {\n    if (!(v instanceof Serializable)) throw new IllegalStateException(\"non-serializable state: \" + v.getClass());\n}","typeGuard":null,"tryCatchPattern":"try {\n    saver.insertCheckpoint(threadId, cp);\n} catch (Exception e) {\n    if (isTransient(e.getCause())) retryWithBackoff(() -> saver.insertCheckpoint(threadId, cp));\n    else throw e;\n}","preventionTips":["Create the checkpoint table at deployment time (schema init).","Only store Serializable objects in graph state.","Size max_allowed_packet and the connection pool for your state blob sizes."],"tags":["mysql","checkpoint","insert","transaction","serialization"],"backgroundTag":"database-write-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"}