{"record":{"id":"3715c2d7f1fe1094","repo":"apache/iceberg","slug":"failed-to-remove-lock-s-3715c2","errorCode":null,"errorMessage":"Failed to remove lock %s","messagePattern":"Failed to remove lock (.+?)","errorType":"exception","errorClass":"UncheckedSQLException","httpStatus":null,"severity":"error","filePath":"flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java","lineNumber":273,"sourceCode":"                  sql.setString(2, lockId);\n                  sql.setString(3, instanceId);\n                  long count = sql.executeUpdate();\n                  LOG.info(\n                      \"Deleted {} lock with instanceId {} with row count {}\",\n                      this,\n                      instanceId,\n                      count);\n                }\n\n                return null;\n              });\n        }\n      } catch (InterruptedException e) {\n        Thread.currentThread().interrupt();\n        throw new UncheckedInterruptedException(e, \"Interrupted during unlock\");\n      } catch (SQLException e) {\n        // SQL exception happened when getting/updating lock information\n        throw new UncheckedSQLException(e, \"Failed to remove lock %s\", this);\n      }\n    }\n\n    @Override\n    public String toString() {\n      return MoreObjects.toStringHelper(this).add(\"type\", type).add(\"lockId\", lockId).toString();\n    }\n\n    @SuppressWarnings(\"checkstyle:NestedTryDepth\")\n    private String instanceId() {\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                  if (rs.next()) {","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java#L255-L291","documentation":"unlock() in JdbcLockFactory hits a SQLException while reading or updating the lock rows in the JDBC catalog table, so the lock could not be removed. The original SQLException is wrapped in UncheckedSQLException and includes the lock's toString() (type and lockId) for diagnosis.","triggerScenarios":"Calling JdbcLock.unlock() when the underlying SQL statements to fetch/update/delete the lock row fail: connection loss, table missing, constraint violation, or DB timeout.","commonSituations":"Database restarted or connection pool closed mid-maintenance; lock table schema mismatch after catalog upgrade; network partition to JDBC metastore; wrong jdbc catalog config pointing to a database without the lock table.","solutions":["Check the wrapped SQLException cause for the root DB error (connectivity, missing table, permissions)","Verify the JDBC connection is healthy and the lock table exists with the expected schema","Retry the maintenance cycle; unlock failure typically leaves the lock for the next attempt","Increase JDBC connection/validation timeouts if transient network issues are the cause"],"exampleFix":"// before\nlockFactory.tryLock(); // UncheckedSQLException: Failed to remove lock\n// after\ntry {\n  lockFactory.tryLock();\n} catch (UncheckedSQLException e) {\n  LOG.error(\"Lock removal failed for {}\", e.getCause(), e); // inspect root SQLException\n}","handlingStrategy":"retry","validationCode":"// verify DB reachability before maintenance\ntry (Connection c = DriverManager.getConnection(jdbcUrl, user, pass)) { c.isValid(5); }","typeGuard":null,"tryCatchPattern":"try { lock.unlock(); } catch (UncheckedSQLException e) { LOG.error(\"unlock failed: {}\", e.getCause()); /* retry next cycle */ }","preventionTips":["Keep the JDBC lock table schema in sync with the catalog version","Monitor DB connectivity from Flink task managers","Grant the lock-table user read/write/delete privileges","Use a connection pool with validation queries"],"tags":["jdbc","sql","locking","database"],"backgroundTag":"database-write-failed","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}