{"record":{"id":"ff6c30827255e4de","repo":"apache/iceberg","slug":"failed-to-check-the-state-of-the-lock-s","errorCode":null,"errorMessage":"Failed to check the state of the lock %s","messagePattern":"Failed to check the state of the lock (.+?)","errorType":"exception","errorClass":"UncheckedSQLException","httpStatus":null,"severity":"error","filePath":"flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java","lineNumber":230,"sourceCode":"    @Override\n    public boolean isHeld() {\n      try {\n        return pool.run(\n            conn -> {\n              try (PreparedStatement sql = conn.prepareStatement(GET_LOCK_SQL)) {\n                sql.setString(1, type.key);\n                sql.setString(2, lockId);\n                try (ResultSet rs = sql.executeQuery()) {\n                  return rs.next();\n                }\n              }\n            });\n      } catch (InterruptedException e) {\n        Thread.currentThread().interrupt();\n        throw new UncheckedInterruptedException(e, \"Interrupted during isHeld\");\n      } catch (SQLException e) {\n        // SQL exception happened when getting lock information\n        throw new UncheckedSQLException(e, \"Failed to check the state of the lock %s\", this);\n      }\n    }\n\n    @SuppressWarnings(\"checkstyle:NestedTryDepth\")\n    @Override\n    public void unlock() {\n      try {\n        // Possible concurrency issue:\n        // - `unlock` and `tryLock` happens at the same time when there is an existing lock\n        //\n        // Steps:\n        // 1. `unlock` removes the lock in the database, but there is a temporary connection failure\n        // 2. `lock` finds that there is no lock, so creates a new lock\n        // 3. `unlock` retries the lock removal and removes the new lock\n        //\n        // To prevent the situation above we fetch the current lockId, and remove the lock\n        // only with the given id.\n        String instanceId = instanceId();","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java#L212-L248","documentation":"JdbcLockFactory's JdbcLock.isHeld() queries the JDBC lock table to determine whether this trigger holds the maintenance lock. Any SQLException from the underlying JDBC connection/query is wrapped into UncheckedSQLException with this message. The error means the lock state could not be read, not that the lock is (or is not) held.","triggerScenarios":"tryLock() -> isHeld() executing SELECT against the JDBC lock table fails with a SQLException: bad JDBC URI, database down, table missing (schema not initialized), credentials revoked, or connection dropped mid-query.","commonSituations":"JDBC catalog database restarted or unreachable during maintenance trigger creation; lock table dropped/recreated; network partition between Flink task manager and the RDS/Postgres host; wrong username/password in the JDBC connection config.","solutions":["Verify the database is reachable and the lock table exists (run the JdbcCatalog table-create SQL against it).","Test credentials in the JDBC URI by connecting with a plain SQL client.","Check network/firewall/Security Group rules between the Flink cluster and the DB host.","Inspect the cause (UncheckedSQLException.getCause()) for the exact SQLState to distinguish connectivity from schema/permission problems.","If transient, retry triggerLock/table maintenance after the DB recovers; the exception is unchecked so callers must catch UncheckedSQLException."],"exampleFix":"// before\nString jdbcUrl = \"jdbc:mysql://db-host:3306/iceberg\"; // db down -> UncheckedSQLException\nTableMaintenance.forTable(table).lockFactory(JdbcLockFactory.builder().setJdbcUrl(jdbcUrl).build());\n// after\n// pre-check connectivity before wiring the lock factory\ntry (Connection c = DriverManager.getConnection(jdbcUrl, user, pass)) { /* ok */ }\nTableMaintenance.forTable(table).lockFactory(JdbcLockFactory.builder().setJdbcUrl(jdbcUrl).build());","handlingStrategy":"try-catch","validationCode":"try (Connection c = DriverManager.getConnection(jdbcUrl, user, pass)) {\n  try (Statement s = c.createStatement()) { s.execute(\"SELECT 1 FROM trigger_lock LIMIT 1\"); }\n}","typeGuard":null,"tryCatchPattern":"try {\n  factory.tryLock(...);\n} catch (UncheckedSQLException e) {\n  LOG.error(\"JDBC lock check failed\", e.getCause());\n  // fall back: skip maintenance this cycle\n}","preventionTips":["Create/verify the JDBC lock table before enabling trigger locking","Test JDBC URL and credentials with a SQL client from the Flink host","Grant SELECT/INSERT/UPDATE/DELETE on the lock table to the JDBC user","Monitor DB availability and set sane connection/socket timeouts"],"tags":["flink","jdbc","lock","sql","maintenance"],"backgroundTag":"database-query-failed","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}