apache/seatunnel · warning

[FileSchemaEvolution] DROP event references unknown column

Error message

[FileSchemaEvolution] DROP event references unknown column '{}' — ignored

What it means

A WARN from AbstractWriteStrategy.updateSinkColumnNames during schema evolution: an AlterTableDropColumnEvent named a column that does not exist in the current sink schema (comparison is case-insensitive), so the DROP is ignored and the file schema is left unchanged. This prevents index-out-of-bounds or silent corruption from stale/mismatched CDC events.

Solutions

  1. Verify the column actually exists in the sink schema (check the SeaTunnel catalog table definition)
  2. If replaying CDC, start from a binlog position consistent with the current sink schema
  3. Align the sink schema with the source (add the column, or rebuild the target table) so subsequent DROP events apply
  4. If the drop was expected to be ignored, this warn is safe to disregard
Defensive patterns

Strategy: validation

Validate before calling

// before applying DROP events, check membership (case-insensitive):
boolean exists = sinkColumnNames.stream()
    .anyMatch(c -> c.equalsIgnoreCase(dropColumn));
if (!exists) log.warn("DROP ignored: column {} not in sink schema", dropColumn);

Prevention

When it happens

Trigger: applySchemaChange -> updateSinkColumnNames receives a DROP event whose column was already dropped upstream, was never part of the sink projection (source selects a subset), or differs due to case handled correctly but still absent from sinkColumnNames.

Common situations: Replaying CDC from an earlier binlog position re-sending old DROP events; multiple upstream pipelines both dropping the same column; source table renamed/recreated while SeaTunnel job ran; schema mismatch between source snapshot and event stream.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/0a827a17232e0a5d. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-connectors-v2/connector-file/connector-file-base/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sink/writer/AbstractWriteStrategy.java:358

            boolean alreadyPresent =
                    sinkColumnNames.stream().anyMatch(c -> c.equalsIgnoreCase(newCol));
            if (!alreadyPresent) {
                if (e.isFirst()) {
                    sinkColumnNames.add(0, newCol);
                } else if (e.getAfterColumn() != null) {
                    int pos = indexOfIgnoreCase(sinkColumnNames, e.getAfterColumn());
                    sinkColumnNames.add(pos >= 0 ? pos + 1 : sinkColumnNames.size(), newCol);
                } else {
                    sinkColumnNames.add(newCol);
                }
            }
        } else if (event instanceof AlterTableDropColumnEvent) {
            // Case-insensitive removal: CDC sources may send column names in any case
            String toDrop = ((AlterTableDropColumnEvent) event).getColumn();
            boolean removed = sinkColumnNames.removeIf(c -> c.equalsIgnoreCase(toDrop));
            if (!removed) {
                log.warn(
                        "[FileSchemaEvolution] DROP event references unknown column '{}' — ignored",
                        toDrop);
            }
        } else if (event instanceof AlterTableChangeColumnEvent) {
            // RENAME (and optional MOVE): remove old name, insert new name at target position.
            // AlterTableChangeColumnEvent covers MySQL's CHANGE COLUMN which can rename and
            // reorder in one statement. Both the rename and the position change are applied.
            AlterTableChangeColumnEvent e = (AlterTableChangeColumnEvent) event;
            int idx = indexOfIgnoreCase(sinkColumnNames, e.getOldColumn());
            if (idx >= 0) {
                sinkColumnNames.remove(idx);
                String newName = e.getColumn().getName();
                if (e.isFirst()) {
                    sinkColumnNames.add(0, newName);
                } else if (e.getAfterColumn() != null) {
                    int afterIdx = indexOfIgnoreCase(sinkColumnNames, e.getAfterColumn());
                    sinkColumnNames.add(
                            afterIdx >= 0 ? afterIdx + 1 : sinkColumnNames.size(), newName);
                } else {

View on GitHub (pinned to cf67b549a7)