{"record":{"id":"f9b80217c2a8c6a2","repo":"apache/seatunnel","slug":"datatypechanger-not-reset","errorCode":null,"errorMessage":"DataTypeChanger not reset","messagePattern":"DataTypeChanger not reset","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"seatunnel-api/src/main/java/org/apache/seatunnel/api/table/schema/handler/DataTypeChangeEventHandler.java","lineNumber":33,"sourceCode":" * limitations under the License.\n */\n\npackage org.apache.seatunnel.api.table.schema.handler;\n\nimport org.apache.seatunnel.api.table.schema.event.SchemaChangeEvent;\nimport org.apache.seatunnel.api.table.type.SeaTunnelRowType;\n\n/** @deprecated instead by {@link TableSchemaChangeEventHandler} */\n@Deprecated\npublic interface DataTypeChangeEventHandler extends SchemaChangeEventHandler<SeaTunnelRowType> {\n\n    SeaTunnelRowType get();\n\n    DataTypeChangeEventHandler reset(SeaTunnelRowType dataType);\n\n    default SeaTunnelRowType handle(SchemaChangeEvent event) {\n        if (get() == null) {\n            throw new IllegalStateException(\"DataTypeChanger not reset\");\n        }\n\n        try {\n            return apply(event);\n        } finally {\n            reset(null);\n            if (get() != null) {\n                throw new IllegalStateException(\"DataTypeChanger not reset\");\n            }\n        }\n    }\n\n    SeaTunnelRowType apply(SchemaChangeEvent event);\n}\n","sourceCodeStart":15,"sourceCodeEnd":48,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-api/src/main/java/org/apache/seatunnel/api/table/schema/handler/DataTypeChangeEventHandler.java#L15-L48","documentation":"DataTypeChangeEventHandler.handle requires the handler to have been initialized with a data type via reset(SeaTunnelRowType) before processing events. If get() returns null, no data type was ever set, so applying a schema-change event that needs the current type fails immediately with IllegalStateException.","triggerScenarios":"Calling handle(event) on a fresh/reset DataTypeChangeEventHandler without first calling reset(dataType) — e.g. reusing an event-handler instance across schema snapshots, or a connector forgetting to initialize the handler after obtaining it.","commonSituations":"Custom connector schema-evolution code constructing the handler and calling handle directly; handler instances recycled between CDC tasks without re-initialization after a checkpoint restore.","solutions":["Call reset(currentSeaTunnelRowType) with the table's current row type before invoking handle(event).","Ensure the handler is re-initialized after task restart/restore before consuming schema-change events.","Guard the call site: only call handle when the handler has a non-null current type.","Create a new handler instance per table/snapshot instead of sharing one."],"exampleFix":"// before\nDataTypeChangeEventHandler h = new MyHandler();\nSeaTunnelRowType t = h.handle(event); // IllegalStateException\n// after\nDataTypeChangeEventHandler h = new MyHandler().reset(currentRowType);\nSeaTunnelRowType t = h.handle(event);","handlingStrategy":"validation","validationCode":"if (handler.get() == null) { handler.reset(currentRowType); } SeaTunnelRowType next = handler.handle(event);","typeGuard":"boolean initialized = handler.get() != null;","tryCatchPattern":"try { return handler.handle(event); } catch (IllegalStateException e) { handler.reset(currentRowType); return handler.handle(event); }","preventionTips":["Always call reset(dataType) before handle()","Re-initialize handlers after restore/restart","Scope one handler instance per table snapshot"],"tags":["schema-change","lifecycle","initialization","cdc"],"backgroundTag":"invalid-state-transition","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"}