{"record":{"id":"a3010d482ab84837","repo":"apache/seatunnel","slug":"column-not-found-in-columns-for-table","errorCode":null,"errorMessage":"Column '{}' not found in {}.COLUMNS for table {}; assuming NOT NULL","messagePattern":"Column '(.+?)' not found in (.+?)\\.COLUMNS for table (.+?); assuming NOT NULL","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/dialect/sqlserver/SqlServerDialect.java","lineNumber":551,"sourceCode":"    private boolean columnIsNullable(Connection connection, TablePath tablePath, String column)\n            throws SQLException {\n        // Prefix with the target database name so the query works even when the JDBC connection\n        // is connected to a different database (e.g. master with no databaseName in the URL).\n        String databaseName = tablePath.getDatabaseName();\n        String infoSchemaPrefix =\n                StringUtils.isNotBlank(databaseName)\n                        ? quoteDatabaseIdentifier(databaseName) + \".INFORMATION_SCHEMA\"\n                        : \"INFORMATION_SCHEMA\";\n        String selectColumnSQL =\n                String.format(\n                        \"SELECT IS_NULLABLE FROM %s.COLUMNS WHERE %s AND COLUMN_NAME = '%s';\",\n                        infoSchemaPrefix, buildCommonWhereClause(tablePath), column);\n        try (Statement statement = connection.createStatement()) {\n            ResultSet rs = statement.executeQuery(selectColumnSQL);\n            if (!rs.next()) {\n                // Column not found — default to non-nullable to avoid incorrectly appending\n                // NULL to an ALTER COLUMN statement for a column that doesn't allow nulls.\n                log.warn(\n                        \"Column '{}' not found in {}.COLUMNS for table {}; assuming NOT NULL\",\n                        column,\n                        infoSchemaPrefix,\n                        tablePath.getFullName());\n                return false;\n            }\n            return rs.getString(\"IS_NULLABLE\").equals(\"YES\");\n        }\n    }\n\n    /**\n     * Returns the SQL column type string to use in DDL statements.\n     *\n     * <p>When source and sink are the same catalog (SQL Server to SQL Server) we prefer the\n     * original {@code sourceType} because it already carries the full type expression (e.g. {@code\n     * varchar(255)}). However, when the CDC schema-change path produces a column whose {@code\n     * sourceType} is a bare type name without length/precision (e.g. {@code varchar} instead of\n     * {@code varchar(255)}), SQL Server rejects the resulting DDL statement. In that case we fall","sourceCodeStart":533,"sourceCodeEnd":569,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/dialect/sqlserver/SqlServerDialect.java#L533-L569","documentation":"While deciding whether an ALTER COLUMN statement needs NULL/NOT NULL, the dialect queries INFORMATION_SCHEMA.COLUMNS for the target column. If the row is absent, the code conservatively assumes the column is NOT NULL (so it will not append NULL) and logs a warning instead of failing.","triggerScenarios":"columnIsNullable is called during applySchemaChange on a SQL Server connection whose SELECT from <prefix>.COLUMNS (with the dialect's WHERE clause) returns no row — typically a typo'd schema/table/column name, wrong infoSchemaPrefix (wrong database), or case/name mismatch (e.g. bracketed or quoted naming differences).","commonSituations":"Schema evolution targeting a different database than expected (missing database prefix), column renamed upstream so the metadata lookup misses, temporary/staging tables not yet visible in INFORMATION_SCHEMA, case-sensitive collation mismatches.","solutions":["Verify the tablePath and column name match exactly what is in INFORMATION_SCHEMA.COLUMNS (including case and schema/database prefix).","Check that the connection points at the intended database/catalog; the infoSchemaPrefix must resolve to the right DB.","Run the generated SELECT against the target DB manually to see why the column row is missing.","Ensure the table exists before schema evolution runs (ordering issue in the DDL plan)."],"exampleFix":"// before: column name case mismatch\ncolumn = \"UserId\"; // actual DB column: user_id\n// after\ncolumn = \"user_id\"; // match INFORMATION_SCHEMA.COLUMNS exactly","handlingStrategy":"validation","validationCode":"// Verify the column exists before schema evolution:\nSELECT COLUMN_NAME, IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS\nWHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND COLUMN_NAME = ?;","typeGuard":null,"tryCatchPattern":"try { applySchemaChange(...); } catch (SQLException e) { log.warn(\"Column metadata lookup may have missed; verify name/case in INFORMATION_SCHEMA.COLUMNS\", e); }","preventionTips":["Match column/table names exactly, including case, against INFORMATION_SCHEMA","Ensure the JDBC connection targets the correct database so the schema prefix resolves","Run schema-evolution DDL in dependency order (table creation first)"],"tags":["jdbc","sqlserver","metadata","schema-evolution"],"backgroundTag":"record-not-found","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"}