{"record":{"id":"46b27ea0e448c8fc","repo":"alibaba/druid","slug":"error","errorCode":null,"errorMessage":"Error","messagePattern":"Error","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/com/alibaba/druid/pool/DruidDataSource.java","lineNumber":1810,"sourceCode":"        lastErrorTimeMillis = System.currentTimeMillis();\n\n        if (t instanceof SQLException) {\n            SQLException sqlEx = (SQLException) t;\n\n            // broadcastConnectionError\n            ConnectionEvent event = new ConnectionEvent(pooledConnection, sqlEx);\n            for (ConnectionEventListener eventListener : holder.getConnectionEventListeners()) {\n                eventListener.connectionErrorOccurred(event);\n            }\n\n            // exceptionSorter.isExceptionFatal\n            if (exceptionSorter != null && exceptionSorter.isExceptionFatal(sqlEx)) {\n                handleFatalError(pooledConnection, sqlEx, sql);\n            }\n\n            throw sqlEx;\n        } else {\n            throw new SQLException(\"Error\", t);\n        }\n    }\n\n    protected final void handleFatalError(\n            DruidPooledConnection conn,\n            SQLException error,\n            String sql\n    ) throws SQLException {\n        final DruidConnectionHolder holder = conn.holder;\n\n        if (conn.isTraceEnable()) {\n            activeConnectionLock.lock();\n            try {\n                if (conn.isTraceEnable()) {\n                    activeConnections.remove(conn);\n                    conn.setTraceEnable(false);\n                }\n            } finally {","sourceCodeStart":1792,"sourceCodeEnd":1828,"githubUrl":"https://github.com/alibaba/druid/blob/fa8dc9912637a2f729eef9f55356621fec18d40e/core/src/main/java/com/alibaba/druid/pool/DruidDataSource.java#L1792-L1828","documentation":"Thrown by DruidAbstractDataSource.handleConnectionException() when a non-SQLException Throwable escapes from a pooled connection operation. Druid wraps it in SQLException(\"Error\", t) so callers that only catch SQLException still see it. The 'Error' literal is intentionally generic because the original is not a SQL error type.","triggerScenarios":"A user of DruidPooledConnection calls handleException(t) (or Druid invokes handleConnectionException) with a Throwable that is not a SQLException — e.g. a java.lang.Error (OutOfMemoryError, StackOverflowError), a RuntimeException from a custom Filter, or a driver bug throwing a raw RuntimeException. Line 1810 wraps it.","commonSituations":"A custom Filter/ConnectionProxy throwing a RuntimeException; driver bug surfacing as RuntimeException; OOM/StackOverflow during statement execution; third-party wrapper (e.g. P6Spy) throwing non-SQL exceptions; assertion errors in tests against a real connection.","solutions":["Inspect getCause() of the thrown SQLException — it holds the real non-SQL Throwable; fix that root problem.","If a custom Filter throws, have it wrap its failures in SQLException so they propagate cleanly instead of being re-wrapped as 'Error'.","Guard JDBC usage so only SQLException is expected; treat any other Throwable as a serious bug (Error subclass) needing JVM-level attention."],"exampleFix":"// before — filter throws RuntimeException, surfaces as SQLException(\"Error\")\npublic class MyFilter extends FilterAdapter {\n    public void statementExecuteUpdate(FilterChain c, StatementProxy s, String sql) {\n        throw new RuntimeException(\"boom\");\n    }\n}\n\n// after — throw SQLException so callers get a typed SQL failure\nthrow new SQLException(\"boom\", e);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"// narrow: only SQL exceptions are expected from JDBC\nboolean isSql = (t instanceof SQLException);","tryCatchPattern":"try {\n    doJdbcWork(conn);\n} catch (SQLException e) {\n    if (\"Error\".equals(e.getMessage()) && e.getCause() != null\n            && !(e.getCause() instanceof SQLException)) {\n        Throwable real = e.getCause();\n        log.error(\"non-SQL failure in JDBC path\", real);\n        if (real instanceof Error) throw (Error) real; // do not swallow JVM errors\n    }\n    throw e;\n}","preventionTips":["Make custom Filters throw SQLException, not RuntimeException, so they propagate cleanly.","Never swallow the cause of a generic SQLException(\"Error\") — it holds the real failure.","Treat non-SQLException Throwables as serious; rethrow Errors."],"tags":["exception-wrapping","filter","non-sqlexception","connection-pool","diagnostics"],"backgroundTag":null,"analyzedSha":"fa8dc9912637a2f729eef9f55356621fec18d40e","analyzedAt":"2026-08-14T04:55:06.789Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}