{"record":{"id":"ab6f7c4ca306a882","repo":"apache/seatunnel","slug":"failed-to-close-preparedstatement-during-schema-ch","errorCode":null,"errorMessage":"Failed to close PreparedStatement during schema change","messagePattern":"Failed to close PreparedStatement during schema change","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"seatunnel-connectors-v2/connector-databend/src/main/java/org/apache/seatunnel/connectors/seatunnel/databend/sink/DatabendSinkWriter.java","lineNumber":293,"sourceCode":"\n    @Override\n    public void applySchemaChange(SchemaChangeEvent event) {\n        try {\n            // save the current batch\n            executeBatch();\n\n            // update the table schema\n            this.tableSchema = tableSchemaChanger.reset(tableSchema).apply(event);\n\n            // update the catalog table\n            schemaChangeManager.applySchemaChange(sinkTablePath, event);\n\n            // close the old prepared statement\n            if (preparedStatement != null) {\n                try {\n                    preparedStatement.close();\n                } catch (SQLException e) {\n                    log.warn(\"Failed to close PreparedStatement during schema change\", e);\n                } finally {\n                    preparedStatement = null;\n                }\n            }\n\n            // update the insert SQL statement\n            this.insertSql = generateInsertSql(catalogTable, tableSchema);\n\n            this.batchCount = 0;\n\n            log.info(\n                    \"Schema change applied successfully for table {}\", sinkTablePath.getFullName());\n        } catch (Exception e) {\n            throw new DatabendConnectorException(\n                    DatabendConnectorErrorCode.SQL_OPERATION_FAILED,\n                    \"Failed to apply schema change: \" + e.getMessage(),\n                    e);\n        }","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-databend/src/main/java/org/apache/seatunnel/connectors/seatunnel/databend/sink/DatabendSinkWriter.java#L275-L311","documentation":"Logged in DatabendSinkWriter.applySchemaChange() when closing the old PreparedStatement fails with a SQLException after a schema change is detected. The writer closes the old statement before rebuilding the INSERT SQL for the new schema. The close failure is only a warning — the statement reference is nulled regardless, so the schema change still proceeds (the leaked statement is reclaimed on GC).","triggerScenarios":"applySchemaChange() detects the target table schema changed, calls preparedStatement.close(), and the underlying connection is broken/closed so the driver throws SQLException.","commonSituations":"Connection dropped mid-run (network issue, Databend restart); driver-level invalidation of the statement; concurrent close from another thread.","solutions":["Restore/verify the JDBC connection health; if the connection is dead the subsequent re-created statement will also fail","Check the attached stack trace — usually a symptom of an already-broken connection rather than a code bug","Ensure only one thread touches the writer's preparedStatement","If warnings recur, upgrade the Databend JDBC driver to a version with more forgiving close semantics"],"exampleFix":"// before\ntry {\n    preparedStatement.close();\n} catch (SQLException e) {\n    log.warn(\"Failed to close PreparedStatement during schema change\", e);\n}\n// after\ntry {\n    if (isStatementValid(preparedStatement)) {\n        preparedStatement.close();\n    }\n} catch (SQLException e) {\n    log.warn(\"Failed to close PreparedStatement during schema change\", e);\n}","handlingStrategy":"try-catch","validationCode":"if (preparedStatement != null && !preparedStatement.isClosed()) {\n    preparedStatement.close();\n}","typeGuard":"boolean safelyClosable(PreparedStatement ps) {\n    try { return ps != null && !ps.isClosed(); } catch (SQLException e) { return false; }\n}","tryCatchPattern":"try {\n    writer.applySchemaChange(newCatalogTable);\n} catch (SQLException e) {\n    log.error(\"Schema change failed; old statement may not have been closed\", e);\n    // writer nulls the statement anyway; verify new statements work\n}","preventionTips":["Ensure stable connectivity during long-running jobs","Avoid concurrent access to the sink writer's JDBC resources","Watch for this warning as a signal of an earlier connection drop"],"tags":["jdbc","statement","schema-change","resource-cleanup"],"backgroundTag":"database-write-failed","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}