{"record":{"id":"28ab968cf5fb24df","repo":"alibaba/spring-ai-alibaba","slug":"unable-to-load-checkpoint","errorCode":null,"errorMessage":"Unable to load checkpoint","messagePattern":"Unable to load 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/h2/H2Saver.java","lineNumber":356,"sourceCode":"\t\t\tthrow new Exception(\"Unable to load latest checkpoint\", ex);\n\t\t}\n\t}\n\n\t@Override\n\tprotected Optional<Checkpoint> selectCheckpointById(String threadId, String checkpointId) throws Exception {\n\t\ttry (Connection conn = getConnection();\n\t\t\t\tPreparedStatement ps = conn.prepareStatement(SELECT_CHECKPOINT_BY_ID)) {\n\t\t\tps.setString(1, threadId);\n\t\t\tps.setString(2, checkpointId);\n\t\t\ttry (ResultSet rs = ps.executeQuery()) {\n\t\t\t\tif (rs.next()) {\n\t\t\t\t\treturn Optional.of(readCheckpoint(rs));\n\t\t\t\t}\n\t\t\t\treturn Optional.empty();\n\t\t\t}\n\t\t}\n\t\tcatch (SQLException | IOException | ClassNotFoundException ex) {\n\t\t\tthrow new Exception(\"Unable to load checkpoint\", ex);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void insertCheckpoint(String threadId, Checkpoint checkpoint) throws Exception {\n\t\tConnection conn = null;\n\t\ttry (Connection ignored = conn = getConnection()) {\n\t\t\tconn.setAutoCommit(false);\n\t\t\tString persistedThreadId = activeThreadId(conn, threadId);\n\t\t\ttry (PreparedStatement ps = conn.prepareStatement(INSERT_CHECKPOINT)) {\n\t\t\t\tps.setString(1, checkpoint.getId());\n\t\t\t\tps.setString(2, persistedThreadId);\n\t\t\t\tps.setString(3, checkpoint.getNodeId());\n\t\t\t\tps.setString(4, checkpoint.getNextNodeId());\n\t\t\t\tps.setString(5, encodeState(checkpoint.getState()));\n\t\t\t\tps.setString(6, stateSerializer.contentType());\n\t\t\t\tps.executeUpdate();\n\t\t\t}","sourceCodeStart":338,"sourceCodeEnd":374,"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/h2/H2Saver.java#L338-L374","documentation":"H2Saver.selectCheckpointById wraps any SQLException, IOException (deserialization), or ClassNotFoundException thrown while loading a single checkpoint row by id into a generic Exception with message 'Unable to load checkpoint'. It signals that the SELECT or the subsequent deserialization of the stored checkpoint state failed, not that the checkpoint is absent (that returns Optional.empty()).","triggerScenarios":"Calling a checkpoint-loading API (e.g. BaseCheckpointSaver.get/getById backed by H2Saver.selectCheckpointById) when: the H2 query throws (table missing/corrupt, connection failure), the serialized state column is unreadable by the configured stateSerializer (content type changed), or the checkpoint's state class is not on the classpath at read time (ClassNotFoundException).","commonSituations":"Reading checkpoints written by an older library version whose serializer format changed; H2 database file deleted or corrupted; running the app without the classes that implement the graph state (different fat jar); H2 server restarted or connection pool exhausted.","solutions":["Inspect the wrapped cause (getCause()) to distinguish SQL failure vs ClassNotFound vs IO/deserialization failure.","Verify the checkpoints table exists and matches the current H2Saver schema (re-run the saver's table DDL or init).","Ensure the state classes stored in checkpoints are on the runtime classpath and serializable by the configured stateSerializer.","If the checkpoint was written by a different library version, discard old checkpoint data or migrate it with the same serializer version."],"exampleFix":"// before: serializer changed between versions, old blobs unreadable\nH2Saver.builder().stateSerializer(new JacksonStateSerializer(...)).build();\n// after: pin the same serializer/format used to write the checkpoints, and check the cause\ntry {\n  saver.get(threadId, checkpointId);\n} catch (Exception e) {\n  log.error(\"checkpoint load failed\", e.getCause()); // see real reason\n}","handlingStrategy":"try-catch","validationCode":"// pre-check: schema + cause triage\nif (!tableExists(dataSource, \"checkpoints\")) throw new IllegalStateException(\"checkpoints table missing\");","typeGuard":"boolean loadable(Exception e) { return !(e.getCause() instanceof ClassNotFoundException); }","tryCatchPattern":"try { return saver.get(threadId, checkpointId); }\ncatch (Exception e) {\n  if (e.getCause() instanceof ClassNotFoundException cnf) throw new IllegalStateException(\"state class missing on classpath\", cnf);\n  throw new RuntimeException(\"checkpoint load failed\", e.getCause());\n}","preventionTips":["Pin the serializer format/version used to write checkpoints","Keep state classes on the runtime classpath of every service reading checkpoints","Run schema init/migrations before first checkpoint use"],"tags":["database","serialization","checkpoint","h2"],"backgroundTag":"database-query-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"}