apache/seatunnel · error · FactoryException

Unable to create a sink for identifier 'MultiTableSink'.

Error message

Unable to create a sink for identifier 'MultiTableSink'.

What it means

FactoryUtil.createMultiTableSink wraps any Throwable raised while creating the built-in MultiTableSink (used to write to multiple tables) in a FactoryException. The hard-coded identifier 'MultiTableSink' is always present, so failure is almost always inside the factory's option validation or createSink() call.

Source

Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/table/factory/FactoryUtil.java:282

                            "Unable to create a sink for identifier '%s'.", factoryIdentifier),
                    t);
        }
    }

    public static <IN, StateT, CommitInfoT, AggregatedCommitInfoT>
            SeaTunnelSink<IN, StateT, CommitInfoT, AggregatedCommitInfoT> createMultiTableSink(
                    Map<TablePath, SeaTunnelSink> sinks,
                    ReadonlyConfig options,
                    ClassLoader classLoader) {
        try {
            TableSinkFactory<IN, StateT, CommitInfoT, AggregatedCommitInfoT> factory =
                    new MultiTableSinkFactory();
            MultiTableFactoryContext context =
                    new MultiTableFactoryContext(options, classLoader, sinks);
            ConfigValidator.of(context.getOptions()).validate(factory.optionRule());
            return factory.createSink(context).createSink();
        } catch (Throwable t) {
            throw new FactoryException(
                    "Unable to create a sink for identifier 'MultiTableSink'.", t);
        }
    }

    public static Optional<Catalog> createOptionalCatalog(
            String catalogName,
            ReadonlyConfig readonlyConfig,
            ClassLoader classLoader,
            String factoryIdentifier) {
        Optional<CatalogFactory> optionalFactory =
                discoverOptionalFactory(classLoader, CatalogFactory.class, factoryIdentifier);

        return optionalFactory.map(
                catalogFactory -> {
                    ConfigValidator.of(readonlyConfig).validate(catalogFactory.optionRule());
                    return catalogFactory.createCatalog(catalogName, readonlyConfig);
                });
    }

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Examine the wrapped cause for the exact option-validation or creation error.
  2. Check the multi-table sink options against MultiTableSinkFactory's option rule.
  3. Ensure the underlying sink instances passed in were created successfully.

Example fix

// before
Map<String, Object> opts = new HashMap<>(); // empty, fails validation
// after
Map<String, Object> opts = new HashMap<>();
opts.put("multi_table_sink.fields_change", "EXCEPT"); // options matching the option rule
Defensive patterns

Strategy: try-catch

Validate before calling

ConfigValidator.of(options).validate(new MultiTableSinkFactory().optionRule()); // run before createMultiTableSink

Try / catch

try {
    sink = FactoryUtil.createMultiTableSink(options, classLoader, sinks);
} catch (FactoryException e) {
    LOG.error("MultiTableSink creation failed", e.getCause());
    throw e;
}

Prevention

When it happens

Trigger: Calling FactoryUtil.createMultiTableSink(options, classLoader, sinks) when ConfigValidator rejects the supplied options or the MultiTableSinkFactory.createSink() throws while wrapping the underlying sinks.

Common situations: Invalid multi-table sink options in the job config; underlying sink list contains misconfigured sinks; classloader issues in SeaTunnel Web/cluster deployments.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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