{"record":{"id":"07fd69224f5d2fcf","repo":"apache/seatunnel","slug":"column-already-exists-in-table-skipping-add-07fd69","errorCode":null,"errorMessage":"Column {} already exists in table {}. Skipping add column operation. event: {}","messagePattern":"Column (.+?) already exists in table (.+?)\\. Skipping add column operation\\. event: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"seatunnel-connectors-v2/connector-doris/src/main/java/org/apache/seatunnel/connectors/doris/schema/SchemaChangeManager.java","lineNumber":119,"sourceCode":"                        .getOldColumn()\n                        .equals(changeColumnEvent.getColumn().getName())) {\n                    if (!columnExists(tablePath, changeColumnEvent.getOldColumn())\n                            && columnExists(tablePath, changeColumnEvent.getColumn().getName())) {\n                        log.warn(\n                                \"Column {} already exists in table {}. Skipping change column operation. event: {}\",\n                                changeColumnEvent.getColumn().getName(),\n                                tablePath.getFullName(),\n                                event);\n                        return;\n                    }\n                }\n                applySchemaChange(tablePath, changeColumnEvent);\n            } else if (event instanceof AlterTableModifyColumnEvent) {\n                applySchemaChange(tablePath, (AlterTableModifyColumnEvent) event);\n            } else if (event instanceof AlterTableAddColumnEvent) {\n                AlterTableAddColumnEvent addColumnEvent = (AlterTableAddColumnEvent) event;\n                if (columnExists(tablePath, addColumnEvent.getColumn().getName())) {\n                    log.warn(\n                            \"Column {} already exists in table {}. Skipping add column operation. event: {}\",\n                            addColumnEvent.getColumn().getName(),\n                            tablePath.getFullName(),\n                            event);\n                    return;\n                }\n                applySchemaChange(tablePath, addColumnEvent);\n            } else if (event instanceof AlterTableDropColumnEvent) {\n                AlterTableDropColumnEvent dropColumnEvent = (AlterTableDropColumnEvent) event;\n                if (!columnExists(tablePath, dropColumnEvent.getColumn())) {\n                    log.warn(\n                            \"Column {} does not exist in table {}. Skipping drop column operation. event: {}\",\n                            dropColumnEvent.getColumn(),\n                            tablePath.getFullName(),\n                            event);\n                    return;\n                }\n                applySchemaChange(tablePath, dropColumnEvent);","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-doris/src/main/java/org/apache/seatunnel/connectors/doris/schema/SchemaChangeManager.java#L101-L137","documentation":"This WARN log is emitted by SchemaChangeManager.applySchemaChange when an AlterTableAddColumnEvent arrives for a column that already exists in the target Doris table. The add operation is skipped (early return) so that idempotent replays of schema-change events do not fail the pipeline. The library treats an existing identically-named column as 'add already done'.","triggerScenarios":"columnExists(tablePath, addColumnEvent.getColumn().getName()) returns true when the add event is processed — e.g. the same add event is replayed after checkpoint restore, the schema lock/coordination allowed another writer to add it first, or the user manually added the column to Doris before running the job.","commonSituations":"Restarting a Flink/Spark CDC job from an older savepoint so pending schema events re-execute; a DBA pre-added the column; running two pipelines from the same source database into one Doris table; Doris light-schema-change already applied the column in a prior attempt.","solutions":["Confirm via DESC tbl / SHOW CREATE TABLE that the column exists with the correct type; if it matches, the warning is benign and can be ignored.","If the existing column has the WRONG type, drop it (ALTER TABLE ... DROP COLUMN) and restart the job so the add event runs with the correct definition.","Ensure a single pipeline owns schema changes for this table; disable schema_evolution or point the duplicate pipeline at a different table.","Restart from the latest checkpoint/savepoint so schema events are not replayed from an old offset."],"exampleFix":"// before: replayed ADD COLUMN against a table that already has the column\nALTER TABLE db.tbl ADD COLUMN extra_col INT;\n// after: guard/pre-clean\n// ALTER TABLE db.tbl DROP COLUMN extra_col;  -- if type differs\n// or restart from latest checkpoint so the event is not duplicated","handlingStrategy":"validation","validationCode":"// Pre-check the Doris table before enabling schema evolution\nDESC db.tbl;  -- confirm which columns already exist\n// Skip or pre-drop conflicting columns before (re)starting the job","typeGuard":"boolean addAlreadyApplied(DorisTableSchema schema, String column) {\n    return schema.hasColumn(column);  // if true, expect the skip warning\n}","tryCatchPattern":null,"preventionTips":["Restart from the latest checkpoint to avoid duplicate add events.","Use a dedicated schema-evolution owner per table; disable schema_evolution on duplicate pipelines.","Compare the intended column type with DESC output — an existing same-name column with a different type still needs manual correction.","Avoid pre-adding columns manually when schema_evolution=true."],"tags":["schema-change","doris","idempotency","schema-evolution"],"backgroundTag":"column-already-exists","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"}