apache/seatunnel · error · UnsupportedOperationException

The Factory has not been implemented and the deprecated Plug

Error message

The Factory has not been implemented and the deprecated Plugin will be used.

What it means

Default implementation of TableSinkFactory.createSink throws UnsupportedOperationException to signal that the factory has not implemented the new Factory API. In that case the framework falls back to the deprecated legacy Plugin (SeaTunnelSink) discovery path. Hitting the raw exception directly means the fallback was bypassed or the factory is expected to implement this method.

Source

Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/table/factory/TableSinkFactory.java:44

 * This is an SPI interface, used to create {@link TableSink}. Each plugin need to have it own
 * implementation.
 *
 * @param <IN> row type
 * @param <StateT> state type
 * @param <CommitInfoT> commit info type
 * @param <AggregatedCommitInfoT> aggregated commit info type
 */
public interface TableSinkFactory<IN, StateT, CommitInfoT, AggregatedCommitInfoT> extends Factory {

    /**
     * We will never use this method now. So gave a default implement and return null.
     *
     * @param context TableFactoryContext
     * @return return the sink created by this factory
     */
    default TableSink<IN, StateT, CommitInfoT, AggregatedCommitInfoT> createSink(
            TableSinkFactoryContext context) {
        throw new UnsupportedOperationException(
                "The Factory has not been implemented and the deprecated Plugin will be used.");
    }

    @Deprecated
    default List<String> excludeTablePlaceholderReplaceKeys() {
        return Collections.emptyList();
    }
}

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Implement createSink(TableSinkFactoryContext) in your sink factory, returning a TableSink built from the context.
  2. If relying on the framework, ensure the discovery path falls back to the deprecated plugin instead of calling createSink directly.
  3. Migrate the connector fully off the deprecated Plugin API.
  4. Check whether the connector version in use actually supports the new factory API; upgrade if not.

Example fix

// before
public class MySinkFactory implements TableSinkFactory { /* only deprecated Plugin */ }
// after
public class MySinkFactory implements TableSinkFactory {
    @Override
    public <IN, StateT, CommitInfoT, AggregatedCommitInfoT> TableSink<IN, StateT, CommitInfoT, AggregatedCommitInfoT> createSink(TableSinkFactoryContext context) {
        return new MyTableSink<>(context);
    }
}
Defensive patterns

Strategy: fallback

Validate before calling

if (factory.getClass().getEnclosingClass() == null) { try { factory.getClass().getMethod("createSink", TableSinkFactoryContext.class); } catch (NoSuchMethodException e) { /* default method; use legacy plugin path */ } }

Try / catch

try { return factory.createSink(context); } catch (UnsupportedOperationException e) { return createSinkFromDeprecatedPlugin(context); }

Prevention

When it happens

Trigger: Calling a sink factory's createSink(context) when the concrete TableSinkFactory only implemented the deprecated plugin interfaces and not the new default method, and caller code invokes createSink directly (or a code path that does not perform legacy fallback).

Common situations: Custom sink plugins written against the old deprecated Plugin API that were never migrated to TableSinkFactory; using a connector version where the new factory method is missing; reflection or framework code calling the interface default instead of the deprecated path.

Related errors


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