apache/seatunnel · warning
Column {} already exists in table {}. Skipping change column
Error message
Column {} already exists in table {}. Skipping change column operation. event: {} What it means
This is a WARN log emitted by Doris SchemaChangeManager.applySchemaChange when handling an AlterTableChangeColumnEvent. It means the requested 'rename/change column' operation is skipped because the new column name already exists in the target Doris table while the old column no longer does. The manager treats schema evolution events as idempotent: instead of failing the job (which would break Flink/Spark CDC pipelines that replay events), it logs and returns without executing the ALTER TABLE.
Source
Thrown at seatunnel-connectors-v2/connector-doris/src/main/java/org/apache/seatunnel/connectors/doris/schema/SchemaChangeManager.java:105
* Refresh physical table schema by schema change event
*
* @param event schema change event
* @param tablePath sink table path
*/
public void applySchemaChange(TablePath tablePath, SchemaChangeEvent event) throws IOException {
if (event instanceof AlterTableColumnsEvent) {
for (AlterTableColumnEvent columnEvent : ((AlterTableColumnsEvent) event).getEvents()) {
applySchemaChange(tablePath, columnEvent);
}
} else {
if (event instanceof AlterTableChangeColumnEvent) {
AlterTableChangeColumnEvent changeColumnEvent = (AlterTableChangeColumnEvent) event;
if (!changeColumnEvent
.getOldColumn()
.equals(changeColumnEvent.getColumn().getName())) {
if (!columnExists(tablePath, changeColumnEvent.getOldColumn())
&& columnExists(tablePath, changeColumnEvent.getColumn().getName())) {
log.warn(
"Column {} already exists in table {}. Skipping change column operation. event: {}",
changeColumnEvent.getColumn().getName(),
tablePath.getFullName(),
event);
return;
}
}
applySchemaChange(tablePath, changeColumnEvent);
} else if (event instanceof AlterTableModifyColumnEvent) {
applySchemaChange(tablePath, (AlterTableModifyColumnEvent) event);
} else if (event instanceof AlterTableAddColumnEvent) {
AlterTableAddColumnEvent addColumnEvent = (AlterTableAddColumnEvent) event;
if (columnExists(tablePath, addColumnEvent.getColumn().getName())) {
log.warn(
"Column {} already exists in table {}. Skipping add column operation. event: {}",
addColumnEvent.getColumn().getName(),
tablePath.getFullName(),
event);View on GitHub (pinned to cf67b549a7)
Solutions
- Verify with SHOW CREATE TABLE (or Doris schema) that the rename was already applied; if so, no action is needed — the warning is expected and harmless.
- Check whether multiple jobs/processes are applying schema changes to the same Doris table and ensure only the sink job manages schema evolution.
- If the rename did NOT happen (different column with the same name exists), rename or drop the conflicting column manually, then restart the pipeline.
- Check checkpoint/savepoint state: restart from a clean checkpoint so the schema-change event is not replayed against the already-migrated table.
Example fix
// before: stale replay of rename a->b when b already exists ALTER TABLE db.tbl CHANGE COLUMN a b INT; // after: make the event idempotent or fix the table first // 1) drop/rename the conflicting column: ALTER TABLE db.tbl DROP COLUMN b; // 2) or align upstream schema so the event matches the real table state
Defensive patterns
Strategy: validation
Validate before calling
// Before relying on schema evolution, check current Doris schema
// (e.g. via JDBC/MySQL client):
try (ResultSet rs = stmt.executeQuery("DESC " + tablePath.getFullName())) {
boolean oldExists = false, newExists = false;
while (rs.next()) {
String col = rs.getString(1);
oldExists |= col.equalsIgnoreCase(oldName);
newExists |= col.equalsIgnoreCase(newName);
}
// only expect the rename event if oldExists && !newExists
} Type guard
boolean canApplyRename(DorisTableSchema schema, String oldName, String newName) {
return schema.hasColumn(oldName) && !schema.hasColumn(newName);
} Prevention
- Ensure only one pipeline/job applies schema changes to a given Doris table.
- Restart from the latest checkpoint/savepoint to avoid replaying stale schema events.
- Keep DBAs from manually ALTERing tables managed by SeaTunnel schema evolution.
- Verify upstream rename sequences (a->b, b->c) do not produce stale events on recovery.
When it happens
Trigger: An AlterTableChangeColumnEvent arrives where changeColumnEvent.getOldColumn() != new name, columnExists(tablePath, oldColumn) is false, and columnExists(tablePath, newColumn) is true. Typically the rename was already applied in a previous run/attempts, or the upstream schema was renamed twice (e.g. a->b then b->c, and a stale b->c replay), or another writer created the column concurrently.
Common situations: Replaying a CDC snapshot/WAL after checkpoint restore; running the pipeline against a Doris table that was manually ALTERed by a DBA; two jobs writing schema changes to the same table; resubmitting a job after a partial schema migration succeeded but the pipeline failed downstream.
Related errors
- Column {} already exists in table {}. Skipping add column op
- Column {} does not exist in table {}. Skipping drop column o
- Unsupported schemaChangeEvent : <eventType>
- SCHEMA_CHANGE_FAILED
- SCHEMA_CHANGE_FAILED
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/255d2a3d39f8863a.
Report an issue: GitHub.