{"record":{"id":"95fa5ef1a4a60134","repo":"apache/seatunnel","slug":"proxy-connection-is-null","errorCode":null,"errorMessage":"Proxy Connection is null.","messagePattern":"Proxy Connection is null\\.","errorType":"exception","errorClass":"InvocationTargetException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/executor/CopyManagerProxy.java","lineNumber":50,"sourceCode":"    private static final Logger LOG = LoggerFactory.getLogger(CopyManagerProxy.class);\n    Object connection;\n    Object copyManager;\n    Class<?> connectionClazz;\n    Class<?> copyManagerClazz;\n    Method getCopyAPIMethod;\n    Method copyInMethod;\n\n    CopyManagerProxy(Connection connection)\n            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException,\n                    SQLException {\n        LOG.info(\"Proxy connection class: {}\", connection.getClass().getName());\n        this.connection = connection.unwrap(Connection.class);\n        LOG.info(\"Proxy unwrap connection class: {}\", this.connection.getClass().getName());\n        if (Proxy.isProxyClass(this.connection.getClass())) {\n            InvocationHandler handler = Proxy.getInvocationHandler(this.connection);\n            this.connection = getConnectionFromInvocationHandler(handler);\n            if (null == this.connection) {\n                throw new InvocationTargetException(\n                        new NullPointerException(\"Proxy Connection is null.\"));\n            }\n            LOG.info(\"Proxy connection class: {}\", this.connection.getClass().getName());\n            this.connectionClazz = this.connection.getClass();\n        } else {\n            this.connectionClazz = this.connection.getClass();\n        }\n        this.getCopyAPIMethod = this.connectionClazz.getMethod(\"getCopyAPI\");\n        this.copyManager = this.getCopyAPIMethod.invoke(this.connection);\n        this.copyManagerClazz = this.copyManager.getClass();\n        this.copyInMethod = this.copyManagerClazz.getMethod(\"copyIn\", String.class, Reader.class);\n    }\n\n    long doCopy(String sql, Reader reader)\n            throws InvocationTargetException, IllegalAccessException {\n        return (long) this.copyInMethod.invoke(this.copyManager, sql, reader);\n    }\n","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/executor/CopyManagerProxy.java#L32-L68","documentation":"CopyManagerProxy unwraps the pooled/proxied JDBC Connection to reach the native connection needed for COPY. If the proxy's InvocationHandler cannot yield a real Connection (getConnectionFromInvocationHandler returns null), this error is thrown, since COPY requires the driver's native connection object.","triggerScenarios":"Constructing CopyManagerProxy with a Connection from a connection pool (e.g. HikariCP, DBCP) whose proxy class/InvocationHandler does not expose the underlying native connection in the expected field.","commonSituations":"Using an unsupported pooling library or unusual driver wrapper in front of PostgreSQL; running inside a framework that wraps connections; driver upgrade changed internal proxy structure.","solutions":["Bypass the pool: obtain a raw connection from the driver for the copy executor.","Upgrade SeaTunnel connector-jdbc, which may add support for your pool's proxy layout.","Use a pool/driver combination known to work (e.g. HikariCP with the official PostgreSQL driver).","Log the connection class and InvocationHandler type and check whether it is a supported wrapper."],"exampleFix":"// before: passing pooled connection directly\nConnection conn = dataSource.getConnection();\nnew CopyManagerProxy(conn);\n// after: unwrap first where possible\nConnection native = conn.unwrap(org.postgresql.PGConnection.class).getConnection(); // or pass unwrapped connection","handlingStrategy":"validation","validationCode":"Connection c = dataSource.getConnection();\nif (Proxy.isProxyClass(c.getClass())) {\n  InvocationHandler h = Proxy.getInvocationHandler(c);\n  // ensure handler exposes the native connection before using copy executor\n  LOG.info(\"connection wrapper: {} / {}\", c.getClass(), h.getClass());\n}","typeGuard":"boolean isNativelyUnwrappable(Connection c) {\n  try { c.unwrap(Connection.class); return true; } catch (SQLException e) { return false; }\n}","tryCatchPattern":"try {\n  new CopyManagerProxy(connection);\n} catch (JdbcConnectorException | InvocationTargetException e) {\n  // fall back to a non-copy statement executor for pooled/proxied connections\n}","preventionTips":["Use standard pool + driver combos (HikariCP with the official PostgreSQL driver).","Obtain raw driver connections for COPY-heavy jobs.","Keep connector-jdbc and drivers up to date so proxy layouts match.","Test copy mode against your exact pool/driver versions before production."],"tags":["jdbc","connection-pool","proxy","copy"],"backgroundTag":"internal-invariant-violation","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}