apache/seatunnel · error · IllegalStateException

DataTypeChanger not reset

Error message

DataTypeChanger not reset

What it means

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.

Source

Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/table/schema/handler/DataTypeChangeEventHandler.java:33

 * limitations under the License.
 */

package org.apache.seatunnel.api.table.schema.handler;

import org.apache.seatunnel.api.table.schema.event.SchemaChangeEvent;
import org.apache.seatunnel.api.table.type.SeaTunnelRowType;

/** @deprecated instead by {@link TableSchemaChangeEventHandler} */
@Deprecated
public interface DataTypeChangeEventHandler extends SchemaChangeEventHandler<SeaTunnelRowType> {

    SeaTunnelRowType get();

    DataTypeChangeEventHandler reset(SeaTunnelRowType dataType);

    default SeaTunnelRowType handle(SchemaChangeEvent event) {
        if (get() == null) {
            throw new IllegalStateException("DataTypeChanger not reset");
        }

        try {
            return apply(event);
        } finally {
            reset(null);
            if (get() != null) {
                throw new IllegalStateException("DataTypeChanger not reset");
            }
        }
    }

    SeaTunnelRowType apply(SchemaChangeEvent event);
}

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Call reset(currentSeaTunnelRowType) with the table's current row type before invoking handle(event).
  2. Ensure the handler is re-initialized after task restart/restore before consuming schema-change events.
  3. Guard the call site: only call handle when the handler has a non-null current type.
  4. Create a new handler instance per table/snapshot instead of sharing one.

Example fix

// before
DataTypeChangeEventHandler h = new MyHandler();
SeaTunnelRowType t = h.handle(event); // IllegalStateException
// after
DataTypeChangeEventHandler h = new MyHandler().reset(currentRowType);
SeaTunnelRowType t = h.handle(event);
Defensive patterns

Strategy: validation

Validate before calling

if (handler.get() == null) { handler.reset(currentRowType); } SeaTunnelRowType next = handler.handle(event);

Type guard

boolean initialized = handler.get() != null;

Try / catch

try { return handler.handle(event); } catch (IllegalStateException e) { handler.reset(currentRowType); return handler.handle(event); }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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