alibaba/spring-ai-alibaba · critical · RuntimeException
Unable to create tables
Error message
Unable to create tables
What it means
OracleSaver.initTables wraps any SQLException raised while batch-executing the DDL statements that create the checkpoint tables and index into a RuntimeException('Unable to create tables'). This happens during saver initialization when Oracle rejects the CREATE TABLE / CREATE INDEX statements. It means the checkpoint persistence schema could not be set up, so the saver cannot be used.
Source
Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/oracle/OracleSaver.java:579
*/
protected void initTables() {
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
if (createOption == CreateOption.CREATE_OR_REPLACE) {
statement.addBatch(DROP_THREAD_INDEX);
statement.addBatch(DROP_CHECKPOINT_TABLE);
statement.addBatch(DROP_THREAD_TABLE);
}
if (createOption == CreateOption.CREATE_OR_REPLACE ||
createOption == CreateOption.CREATE_IF_NOT_EXISTS) {
statement.addBatch(CREATE_THREAD_TABLE);
statement.addBatch(INDEX_THREAD_TABLE);
statement.addBatch(CREATE_CHECKPOINT_TABLE);
statement.executeBatch();
}
}
catch (SQLException sqlException) {
throw new RuntimeException("Unable to create tables", sqlException);
}
}
/**
* A builder for OracleSaver.
*/
public static class Builder {
private DataSource dataSource;
private CreateOption createOption = CreateOption.CREATE_IF_NOT_EXISTS;
private StateSerializer stateSerializer;
private int maxCachedThreads = 1024;
/**
* Sets the datasource
*
* @param dataSource the datasource
* @return this builder
*/View on GitHub (pinned to f82da0b50f)
Solutions
- Grant the connecting Oracle user CREATE TABLE privilege (GRANT CREATE TABLE TO user) or run initTables as a DBA-backed schema user.
- Check the wrapped SQLException cause for the exact ORA- code; if ORA-00955 (name in use), the tables already exist and you can skip initTables.
- Verify the JDBC URL, service name, and credentials; test connectivity with a simple SELECT 1 FROM DUAL before initializing.
- If initialization is idempotency-related, pre-create the checkpoint tables/index manually with the exact names the saver expects.
Example fix
// before OracleSaver.builder().dataSource(ds).stateSerializer(serializer).build(); // fails: no CREATE TABLE privilege // after // grant DDL rights or pre-create tables, then optionally skip auto-init: // GRANT CREATE TABLE TO app_user; OracleSaver.builder().dataSource(ds).stateSerializer(serializer).build();
Defensive patterns
Strategy: try-catch
Validate before calling
// Java: pre-check privileges and existing tables before initTables
try (Connection c = dataSource.getConnection(); Statement s = c.createStatement()) {
s.execute("SELECT 1 FROM DUAL"); // connectivity
ResultSet rs = c.getMetaData().getTables(null, null, "CHECKPOINTS", new String[]{"TABLE"});
if (rs.next()) { /* tables already exist: skip init */ }
} Try / catch
try {
saverBuilder.build();
} catch (RuntimeException e) {
if ("Unable to create tables".equals(e.getMessage()) && e.getCause() instanceof SQLException sql) {
// inspect sql.getErrorCode() for ORA-00955 / ORA-01031 and act accordingly
}
} Prevention
- Grant CREATE TABLE to the app's DB user or pre-create the schema via migration scripts.
- Run a connectivity smoke query (SELECT 1 FROM DUAL) before saver initialization.
- Make table creation idempotent and managed by DB migrations instead of app startup.
- Always log the wrapped SQLException cause and Oracle error code.
When it happens
Trigger: Calling OracleSaver builder initTables (or constructing a saver that auto-initializes) when the DB user lacks CREATE TABLE privilege, a table with the same name already exists with an incompatible definition, the connection points to an unreachable/invalid schema, or Oracle throws ORA- errors on the DDL batch (e.g. ORA-00955 name already used, ORA-01031 insufficient privileges).
Common situations: Deploying to an Oracle account with read/write but no DDL permissions; pointing at a shared schema where the checkpoint tables already exist; wrong JDBC URL or service name; network/credentials problems surfacing as SQL exceptions during DDL.
Related errors
- Unable to load checkpoints
- Unable to load latest checkpoint
- Unable to load checkpoint
- Unable to insert checkpoint
- Unable to update checkpoint
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/83d27328ac26811a.
Report an issue: GitHub.