{"record":{"id":"2a55ecab723ca3e5","repo":"apache/iceberg","slug":"failed-to-check-the-state-of-the-lock-s-2a55ec","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/v2.2/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/v2.2/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java#L212-L248","documentation":"JdbcLock.isHeld() throws UncheckedSQLException when the JDBC query against the lock table fails with a SQLException. The message includes the lock identity (%s = lock toString) so you can see which maintenance trigger lock could not be checked. This indicates a database-level problem rather than an interruption.","triggerScenarios":"tryLock -> isHeld executes a SQL query on the lock table and the driver throws SQLException: bad connection, lock table missing, SQL syntax incompatibility, permissions, or database outage.","commonSituations":"Database restarted or connection pool evicted stale connections; lock table (created by JdbcCatalog) was dropped or the table name differs; using a database dialect with incompatible SQL; insufficient privileges for the maintenance user.","solutions":["Check database connectivity with the same JDBC URL/credentials and fix the underlying SQLException (see the wrapped cause).","Verify the lock table exists and is accessible: run the catalog initialization / create the table manually if dropped.","Enable connection pool validation (test-on-borrow / keepalive) to remove stale connections before queries.","Grant the maintenance user SELECT/UPDATE privileges on the lock table.","Retry the maintenance trigger after the database recovers; this error is usually transient."],"exampleFix":"// before\nString url = \"jdbc:mysql://db:3306/iceberg\"; // table missing -> SQLException\n// after\n// ensure lock table exists, e.g. run JdbcCatalog initializeCatalogObjects()\n// or create: CREATE TABLE iceberg_locks (lock_id VARCHAR(255) PRIMARY KEY, ...);\nString url = \"jdbc:mysql://db:3306/iceberg?autoReconnect=true&socketTimeout=60000\";","handlingStrategy":"retry","validationCode":"// verify DB reachability before running maintenance\ntry (Connection c = DriverManager.getConnection(jdbcUrl, user, pass)) { if (!c.isValid(5)) throw new IllegalStateException(\"DB not reachable\"); }","typeGuard":null,"tryCatchPattern":"try { boolean held = lock.tryLock(); } catch (UncheckedSQLException e) { log.error(\"Lock check failed: {}\", e.getCause(), e); /* alert + retry later */ }","preventionTips":["Keep the JDBC catalog's lock table initialized and never drop it independently.","Enable connection pool validation (test-on-borrow/keepalive) to avoid stale connections.","Grant the maintenance user full privileges on the lock table.","Monitor database health and retry maintenance after transient outages."],"tags":["jdbc","sql","lock","flink","database"],"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"}