apache/iceberg · error · UncheckedSQLException
Failed to check the state of the lock %s
Error message
Failed to check the state of the lock %s
What it means
Thrown by JdbcLock.isHeld when the SELECT that checks lock ownership fails with a SQLException. The lock state cannot be determined, so the caller gets an UncheckedSQLException wrapping the original SQL error. tryLock uses isHeld in its recovery path, so this can also surface during lock acquisition retries.
Source
Thrown at flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java:230
@Override
public boolean isHeld() {
try {
return pool.run(
conn -> {
try (PreparedStatement sql = conn.prepareStatement(GET_LOCK_SQL)) {
sql.setString(1, type.key);
sql.setString(2, lockId);
try (ResultSet rs = sql.executeQuery()) {
return rs.next();
}
}
});
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new UncheckedInterruptedException(e, "Interrupted during isHeld");
} catch (SQLException e) {
// SQL exception happened when getting lock information
throw new UncheckedSQLException(e, "Failed to check the state of the lock %s", this);
}
}
@SuppressWarnings("checkstyle:NestedTryDepth")
@Override
public void unlock() {
try {
// Possible concurrency issue:
// - `unlock` and `tryLock` happens at the same time when there is an existing lock
//
// Steps:
// 1. `unlock` removes the lock in the database, but there is a temporary connection failure
// 2. `lock` finds that there is no lock, so creates a new lock
// 3. `unlock` retries the lock removal and removes the new lock
//
// To prevent the situation above we fetch the current lockId, and remove the lock
// only with the given id.
String instanceId = instanceId();View on GitHub (pinned to 86d9c8fc54)
Solutions
- Read the wrapped SQLException (getCause) for the exact SQL error and fix accordingly
- Verify the lock table still exists and the configured user has SELECT on it
- Check connection pool sizing and DB connectivity/network stability from the taskmanager
- Retry the operation — transient connection errors often resolve on the next attempt
Example fix
// before: granting read-only access but revoking SELECT on lock tables REVOKE SELECT ON iceberg_lock FROM maintenance_user; // isHeld fails // after: keep SELECT on the lock tables for the maintenance user GRANT SELECT ON iceberg_lock TO maintenance_user;
Defensive patterns
Strategy: retry
Validate before calling
// preflight: lock table exists and is readable
try (Connection c = ds.getConnection();
ResultSet rs = c.createStatement().executeQuery("SELECT 1 FROM iceberg_lock LIMIT 1")) {
// OK
} catch (SQLException e) { alert("Lock table check failed: " + e.getMessage()); } Try / catch
try {
maintenanceResult = trigger.withLock(...);
} catch (UncheckedSQLException e) {
if (isTransient(e)) { backoffAndRetry(); } else { throw e; }
} Prevention
- Keep SELECT privileges on lock tables for the maintenance user across permission changes
- Use connection pool validation (test-on-borrow) to prune dead connections
- Monitor DB uptime; alert on lock table schema changes
- Retry transient SQL states (e.g. connection errors) with backoff
When it happens
Trigger: The lock-state SELECT fails: connection dropped mid-query, lock table dropped or altered, wrong schema/table name, database timeout, or permissions on SELECT revoked.
Common situations: Database connection pool exhaustion under load; network blip between Flink taskmanager and the JDBC database; someone manually dropped or renamed the lock table; DB user permissions changed.
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
- Failed to get lock information for %s
- Failed to create %s lock
- Failed to remove lock %s
- Cannot initialize JDBC table maintenance lock
- Failed to check the state of the lock %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/a10edf9c1ed5f157.
Report an issue: GitHub.