apache/iceberg · error · UncheckedSQLException

Failed to get lock information for %s

Error message

Failed to get lock information for %s

What it means

JdbcLockFactory.instanceId() could not read/write lock information in the JDBC lock table while computing a unique instance id; the SQLException is wrapped into UncheckedSQLException with this message. No instance id could be established, so trigger locking cannot proceed.

Source

Thrown at flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java:303

        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()) {
                  if (rs.next()) {
                    return rs.getString(1);
                  } else {
                    return null;
                  }
                }
              }
            });
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new UncheckedInterruptedException(e, "Interrupted during unlock");
      } catch (SQLException e) {
        throw new UncheckedSQLException(e, "Failed to get lock information for %s", type);
      }
    }
  }

  private enum Type {
    MAINTENANCE("m"),
    RECOVERY("r");

    private final String key;

    Type(String key) {
      this.key = key;
    }
  }
}

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Create the JDBC lock table with the schema expected by JdbcCatalog/JdbcLockFactory before enabling maintenance.
  2. Validate JDBC URL, user and password against the target database with a SQL client.
  3. Grant the JDBC user SELECT/INSERT/UPDATE/DELETE on the lock table.
  4. Retry startup if concurrent instance allocation caused a transient conflict; stagger task manager starts.
  5. Read UncheckedSQLException.getCause() for the exact driver error message.

Example fix

// before
JdbcLockFactory.builder().setJdbcUrl("jdbc:postgresql://host:5432/iceberg") // lock table never created
  .build();
// after
// run first: CREATE TABLE iceberg.maintenance_lock (...) per JdbcCatalog docs
JdbcLockFactory.builder().setJdbcUrl("jdbc:postgresql://host:5432/iceberg").build();
Defensive patterns

Strategy: validation

Validate before calling

try (Connection c = DriverManager.getConnection(jdbcUrl, user, pass)) {
  DatabaseMetaData md = c.getMetaData();
  if (!md.getTables(null, null, "trigger_lock", null).next()) {
    throw new IllegalStateException("Lock table missing - run init SQL");
  }
}

Try / catch

try {
  factory.tableTriggerLock(...);
} catch (UncheckedSQLException e) {
  LOG.error("instanceId allocation failed", e.getCause());
  // retry with backoff once the DB/table is fixed
}

Prevention

When it happens

Trigger: SQLException during instanceId()'s lock-table access: database unreachable, lock table missing, INSERT/SELECT denied, or duplicate/unique-key conflict on lock rows during concurrent startup.

Common situations: First run before the lock table was created; two task managers starting concurrently against a DB with restrictive isolation; credentials valid for SELECT but not INSERT; JDBC URL pointing at a nonexistent database.

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/8002fd59ad619603. Report an issue: GitHub.