t8y2/dbx · critical · PhysicalConnectionStateUnknownException

Physical JDBC connection termination did not complete

Error message

Physical JDBC connection termination did not complete

What it means

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.

Source

Thrown at agents/common/src/main/java/com/dbx/agent/JdbcConnectionPoolRegistry.java:1730

                                ? physicalConnectionCloser.close(
                                    connection,
                                    factoryDataSource,
                                    closeTimeoutMillis
                                )
                                : physicalConnectionCloser.abort(
                                    connection,
                                    (Executor) arguments[0],
                                    factoryDataSource,
                                    closeTimeoutMillis
                                );
                            if (terminated) {
                                setupAttempt.completeAfterPhysicalClose();
                                if (released.compareAndSet(false, true)) {
                                    release();
                                }
                                return null;
                            }
                            throw new PhysicalConnectionStateUnknownException(
                                new SQLException("Physical JDBC connection termination did not complete")
                            );
                        }
                    }
                    if ("isClosed".equals(method.getName()) && method.getParameterCount() == 0) {
                        return released.get() || physicalConnectionCloser.isClosed(
                            connection,
                            factoryDataSource,
                            closeTimeoutMillis
                        );
                    }
                    if ("setNetworkTimeout".equals(method.getName()) && method.getParameterCount() == 2) {
                        physicalConnectionCloser.setNetworkTimeout(
                            connection,
                            (Executor) arguments[0],
                            (Integer) arguments[1],
                            factoryDataSource,
                            closeTimeoutMillis

View on GitHub (pinned to c0390bff16)

Solutions

  1. Increase the close timeout so slow driver closes can complete
  2. Ensure returning connections to the pool happens before executor shutdown
  3. Check DB/network health — a hung close usually indicates a stalled socket or driver bug
  4. Handle PhysicalConnectionStateUnknownException by discarding the pool/data source and rebuilding it, since its state is poisoned

Example fix

// before
connection.close(); // assumes close completes
// after
try {
    connection.close();
} catch (SQLException e) {
    if (hasUnknownPhysicalState(e)) {
        pool.retireAndRebuild(); // pool state is unknown/poisoned
    }
    throw e;
}
Defensive patterns

Strategy: fallback

Validate before calling

// Keep close timeouts sane relative to worst-case driver behavior:
if (driverWorstCaseCloseMillis > configuredCloseTimeoutMillis) {
    increaseCloseTimeout(driverWorstCaseCloseMillis * 2);
}

Type guard

static boolean hasUnknownPhysicalState(Throwable t) {
    while (t != null) {
        if (t instanceof PhysicalConnectionStateUnknownException) return true;
        if (t instanceof SQLException
            && t.getMessage() != null
            && t.getMessage().contains("termination did not complete")) return true;
        t = t.getCause();
    }
    return false;
}

Try / catch

try {
    conn.close();
} catch (SQLException e) {
    if (hasUnknownPhysicalState(e)) {
        pool.retireAndRebuild(); // state unknown: discard poisoned pool
        return;
    }
    throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/b32c7f447465b37e. Report an issue: GitHub.