{"record":{"id":"e08c564d50eb73dd","repo":"apache/iceberg","slug":"cannot-initialize-jdbc-table-maintenance-lock-con-e08c56","errorCode":null,"errorMessage":"Cannot initialize JDBC table maintenance lock: Connection failed","messagePattern":"Cannot initialize JDBC table maintenance lock: Connection failed","errorType":"exception","errorClass":"UncheckedSQLException","httpStatus":null,"severity":"error","filePath":"flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java","lineNumber":152,"sourceCode":"                    LOCK_TABLE_NAME /* tableNamePattern */,\n                    null /* types */)) {\n              if (rs.next()) {\n                LOG.debug(\"Flink maintenance lock table already exists\");\n                return true;\n              }\n            }\n            LOG.info(\"Creating Flink maintenance lock table {}\", LOCK_TABLE_NAME);\n            try (PreparedStatement ps = conn.prepareStatement(CREATE_LOCK_TABLE_SQL)) {\n              ps.execute();\n            }\n\n            return true;\n          });\n    } catch (SQLTimeoutException e) {\n      throw new UncheckedSQLException(\n          e, \"Cannot initialize JDBC table maintenance lock: Query timed out\");\n    } catch (SQLTransientConnectionException | SQLNonTransientConnectionException e) {\n      throw new UncheckedSQLException(\n          e, \"Cannot initialize JDBC table maintenance lock: Connection failed\");\n    } catch (SQLException e) {\n      throw new UncheckedSQLException(e, \"Cannot initialize JDBC table maintenance lock\");\n    } catch (InterruptedException e) {\n      Thread.currentThread().interrupt();\n      throw new UncheckedInterruptedException(e, \"Interrupted in call to initialize\");\n    }\n  }\n\n  private static class JdbcLock implements TriggerLockFactory.Lock {\n    private final JdbcClientPool pool;\n    private final String lockId;\n    private final Type type;\n\n    private JdbcLock(JdbcClientPool pool, String lockId, Type type) {\n      this.pool = pool;\n      this.lockId = lockId;\n      this.type = type;","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java#L134-L170","documentation":"JdbcLockFactory.initializeLockTables also translates SQLTransientConnectionException and SQLNonTransientConnectionException into UncheckedSQLException with the message 'Cannot initialize JDBC table maintenance lock: Connection failed'. It means the JDBC driver could not establish or maintain a connection while creating the lock tables.","triggerScenarios":"JdbcLockFactory.open() when the database is unreachable, credentials/network are broken, max connections are exhausted, or the DB rejects transiently (connection pool saturated).","commonSituations":"Wrong JDBC host/port or security-group/firewall blocking the Flink workers; database restarted or in failover; connection pool exhausted by other jobs; TLS/credential misconfiguration.","solutions":["Check the wrapped SQLException cause for the underlying reason (unknown host, refused, auth)","Verify JDBC URL, credentials, and network reachability from all Flink TaskManagers","Confirm the database is running and has free connection slots (max_connections)","Retry after transient network issues; the source exception is a transient-connection class, so a job restart often succeeds"],"exampleFix":"// before\nJdbcLockFactory.create(\"jdbc:postgresql://db-wrong-host:5432/iceberg\", \"lock_tbl\", props);\n// after\nJdbcLockFactory.create(\"jdbc:postgresql://db-correct-host:5432/iceberg\", \"lock_tbl\", props);","handlingStrategy":"retry","validationCode":"try (Connection c = DriverManager.getConnection(jdbcUrl, user, pass)) {\n  if (!c.isValid(5)) throw new IllegalStateException(\"JDBC connection not valid before opening lock factory\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  lockFactory.open(context);\n} catch (UncheckedSQLException e) {\n  Throwable cause = e.getCause();\n  if (cause instanceof SQLTransientConnectionException) {\n    // transient: retry with backoff\n    return Retries.retryWithBackoff(() -> reopen(context), 3);\n  }\n  throw e; // non-transient: fail fast, likely config/network misconfiguration\n}","preventionTips":["Validate JDBC URL, credentials, and firewall rules for all TaskManagers","Ensure the database has spare connection capacity for maintenance jobs","Distinguish transient vs non-transient SQLException causes to decide retry vs fail-fast"],"tags":["jdbc","network","connection","flink"],"backgroundTag":"connection-refused","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"}