apache/iceberg · critical · UncheckedSQLException
Cannot initialize JDBC table maintenance lock
Error message
Cannot initialize JDBC table maintenance lock
What it means
The generic catch-all in JdbcLockFactory.initializeLockTables: any SQLException that is neither a timeout nor a connection-class exception is wrapped in UncheckedSQLException with this unspecific message.
Source
Thrown at flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java:155
LOG.debug("Flink maintenance lock table already exists");
return true;
}
}
LOG.info("Creating Flink maintenance lock table {}", LOCK_TABLE_NAME);
try (PreparedStatement ps = conn.prepareStatement(CREATE_LOCK_TABLE_SQL)) {
ps.execute();
}
return true;
});
} catch (SQLTimeoutException e) {
throw new UncheckedSQLException(
e, "Cannot initialize JDBC table maintenance lock: Query timed out");
} catch (SQLTransientConnectionException | SQLNonTransientConnectionException e) {
throw new UncheckedSQLException(
e, "Cannot initialize JDBC table maintenance lock: Connection failed");
} catch (SQLException e) {
throw new UncheckedSQLException(e, "Cannot initialize JDBC table maintenance lock");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new UncheckedInterruptedException(e, "Interrupted in call to initialize");
}
}
private static class JdbcLock implements TriggerLockFactory.Lock {
private final JdbcClientPool pool;
private final String lockId;
private final Type type;
private JdbcLock(JdbcClientPool pool, String lockId, Type type) {
this.pool = pool;
this.lockId = lockId;
this.type = type;
}
@OverrideView on GitHub (pinned to 86d9c8fc54)
Solutions
- Inspect the cause chain (UncheckedSQLException.getCause()) for the real SQL error and error code.
- Grant the lock user CREATE/INSERT/SELECT privileges on the lock schema.
- Confirm the database/schema in the URI exists and the JDBC driver matches the server version.
- Enable driver-level logging to capture the failing statement.
Example fix
// before: user without DDL rights
.option("lock.jdbc.user", "readonly_user")
// after
.option("lock.jdbc.user", "iceberg_lock_admin") Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: verify schema and DDL privileges
try (Connection c = DriverManager.getConnection(uri, user, password)) {
DatabaseMetaData md = c.getMetaData();
if (!md.storesLowerCaseIdentifiers() && !md.supportsSchemasInTableDefinitions()) {
throw new IllegalStateException("Unsupported lock database dialect");
}
} Try / catch
try {
lockFactory.open();
} catch (UncheckedSQLException e) {
SQLException sql = (SQLException) e.getCause();
LOG.error("Lock init failed: sqlState={} code={}", sql.getSQLState(), sql.getErrorCode(), sql);
throw e;
} Prevention
- Always inspect the cause chain for the underlying SQL error
- Grant CREATE/INSERT/SELECT on the lock schema to the lock user
- Verify the database/schema in the URI exists
- Match JDBC driver version to the server version
When it happens
Trigger: JdbcLockFactory.open() where initialization SQL fails with a plain SQLException — e.g. SQL syntax errors, missing table privileges, unknown database, driver-specific errors.
Common situations: Lock-table DDL failures because the configured user lacks CREATE privileges, nonexistent schema/database in the URI, incompatible DB dialect or driver version.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- Cannot initialize JDBC table maintenance lock: Query timed o
- Cannot initialize JDBC table maintenance lock: Connection fa
- Cannot initialize JDBC table maintenance lock
- Failed to check the state of the lock %s
- Failed to get lock information for %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/e2a0ca68afcedbaa.
Report an issue: GitHub.