{"record":{"id":"b32c7f447465b37e","repo":"t8y2/dbx","slug":"physical-jdbc-connection-termination-did-not-compl","errorCode":null,"errorMessage":"Physical JDBC connection termination did not complete","messagePattern":"Physical JDBC connection termination did not complete","errorType":"exception","errorClass":"PhysicalConnectionStateUnknownException","httpStatus":null,"severity":"critical","filePath":"agents/common/src/main/java/com/dbx/agent/JdbcConnectionPoolRegistry.java","lineNumber":1730,"sourceCode":"                                ? physicalConnectionCloser.close(\n                                    connection,\n                                    factoryDataSource,\n                                    closeTimeoutMillis\n                                )\n                                : physicalConnectionCloser.abort(\n                                    connection,\n                                    (Executor) arguments[0],\n                                    factoryDataSource,\n                                    closeTimeoutMillis\n                                );\n                            if (terminated) {\n                                setupAttempt.completeAfterPhysicalClose();\n                                if (released.compareAndSet(false, true)) {\n                                    release();\n                                }\n                                return null;\n                            }\n                            throw new PhysicalConnectionStateUnknownException(\n                                new SQLException(\"Physical JDBC connection termination did not complete\")\n                            );\n                        }\n                    }\n                    if (\"isClosed\".equals(method.getName()) && method.getParameterCount() == 0) {\n                        return released.get() || physicalConnectionCloser.isClosed(\n                            connection,\n                            factoryDataSource,\n                            closeTimeoutMillis\n                        );\n                    }\n                    if (\"setNetworkTimeout\".equals(method.getName()) && method.getParameterCount() == 2) {\n                        physicalConnectionCloser.setNetworkTimeout(\n                            connection,\n                            (Executor) arguments[0],\n                            (Integer) arguments[1],\n                            factoryDataSource,\n                            closeTimeoutMillis","sourceCodeStart":1712,"sourceCodeEnd":1748,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/common/src/main/java/com/dbx/agent/JdbcConnectionPoolRegistry.java#L1712-L1748","documentation":"A PhysicalConnectionStateUnknownException wrapping a SQLException 'Physical JDBC connection termination did not complete'. Thrown from the proxy InvocationHandler's termination path (close()) when the physical close result cannot be confirmed — the pool cannot know whether the underlying connection actually closed, so it reports the state as unknown and the data source is typically poisoned.","triggerScenarios":"Calling close() on a pooled (proxied) connection when the physical close executed asynchronously fails to confirm completion within the close timeout — e.g. the close task times out, the executor rejects, or the underlying driver close hangs.","commonSituations":"Hung JDBC drivers that never complete close() (socket stuck in a read); close timeout configured too aggressively low; network partitions mid-close; executor shutdown while a close is in flight.","solutions":["Increase the close timeout so slow driver closes can complete","Ensure returning connections to the pool happens before executor shutdown","Check DB/network health — a hung close usually indicates a stalled socket or driver bug","Handle PhysicalConnectionStateUnknownException by discarding the pool/data source and rebuilding it, since its state is poisoned"],"exampleFix":"// before\nconnection.close(); // assumes close completes\n// after\ntry {\n    connection.close();\n} catch (SQLException e) {\n    if (hasUnknownPhysicalState(e)) {\n        pool.retireAndRebuild(); // pool state is unknown/poisoned\n    }\n    throw e;\n}","handlingStrategy":"fallback","validationCode":"// Keep close timeouts sane relative to worst-case driver behavior:\nif (driverWorstCaseCloseMillis > configuredCloseTimeoutMillis) {\n    increaseCloseTimeout(driverWorstCaseCloseMillis * 2);\n}","typeGuard":"static boolean hasUnknownPhysicalState(Throwable t) {\n    while (t != null) {\n        if (t instanceof PhysicalConnectionStateUnknownException) return true;\n        if (t instanceof SQLException\n            && t.getMessage() != null\n            && t.getMessage().contains(\"termination did not complete\")) return true;\n        t = t.getCause();\n    }\n    return false;\n}","tryCatchPattern":"try {\n    conn.close();\n} catch (SQLException e) {\n    if (hasUnknownPhysicalState(e)) {\n        pool.retireAndRebuild(); // state unknown: discard poisoned pool\n        return;\n    }\n    throw e;\n}","preventionTips":["Set the close timeout generously above the driver's worst-case close latency","Always close pooled connections in try-with-resources before executor shutdown","Monitor DB/network health — hung closes usually mean stalled sockets or driver bugs","Treat PhysicalConnectionStateUnknownException as poison: rebuild the pool rather than reuse it"],"tags":["jdbc","close-timeout","unknown-state","connection-close"],"backgroundTag":"physical-connection-state-unknown","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}