apache/flink · error · IllegalStateException

Multiple compatible client factories found for: {}.

Error message

Multiple compatible client factories found for:
{}.

What it means

Thrown by DefaultExecutorServiceLoader.getExecutorFactory when more than one PipelineExecutorFactory reports isCompatibleWith(configuration) == true. The service loader discovers all factories via SPI and the configuration must unambiguously select exactly one executor (e.g., local, remote, yarn, kubernetes).

Source

Thrown at flink-core/src/main/java/org/apache/flink/core/execution/DefaultExecutorServiceLoader.java:83

                if (factory != null && factory.isCompatibleWith(configuration)) {
                    compatibleFactories.add(factory);
                }
            } catch (Throwable e) {
                if (e.getCause() instanceof NoClassDefFoundError) {
                    LOG.info("Could not load factory due to missing dependencies.");
                } else {
                    throw e;
                }
            }
        }

        if (compatibleFactories.size() > 1) {
            final String configStr =
                    configuration.toMap().entrySet().stream()
                            .map(e -> e.getKey() + "=" + e.getValue())
                            .collect(Collectors.joining("\n"));

            throw new IllegalStateException(
                    "Multiple compatible client factories found for:\n" + configStr + ".");
        }

        if (compatibleFactories.isEmpty()) {
            throw new IllegalStateException("No ExecutorFactory found to execute the application.");
        }

        return compatibleFactories.get(0);
    }

    @Override
    public Stream<String> getExecutorNames() {
        final ServiceLoader<PipelineExecutorFactory> loader =
                ServiceLoader.load(PipelineExecutorFactory.class);

        return StreamSupport.stream(loader.spliterator(), false)
                .map(PipelineExecutorFactory::getName);
    }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Set execution.target explicitly (e.g., yarn-application, kubernetes-application, remote, local) to disambiguate.
  2. Remove conflicting executor JARs from the classpath so only one is compatible.
  3. If a custom factory is involved, narrow its isCompatibleWith to match only its intended configuration.

Example fix

# before
# ambiguous: both local and remote executors are compatible

# after
execution.target: yarn-application
Defensive patterns

Strategy: validation

Validate before calling

// Ensure execution.target is set unambiguously
String target = config.get(ExecutionOptions.TARGET);
if (target == null || target.isEmpty()) {
    throw new IllegalStateException("execution.target must be set to disambiguate executor");
}

Try / catch

try {
    loader.getExecutorFactory(configuration);
} catch (IllegalStateException e) {
    if (e.getMessage().startsWith("Multiple compatible")) { /* set execution.target or remove JARs */ }
}

Prevention

When it happens

Trigger: Multiple executor JARs on the classpath (e.g., both flink-clients and a yarn/k8s executor) where the configuration doesn't disambiguate via execution.target or deployment options. Conflicting or overlapping isCompatibleWith logic across factory implementations.

Common situations: Shipping multiple deployment JARs without setting execution.target. Custom PipelineExecutorFactory implementations with overly broad compatibility checks. Ambiguous 'execution.attached' or 'execution.target' settings.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/2f19d664852ee753. Report an issue: GitHub.