apache/seatunnel · error · UnsupportedOperationException
'%s' source don't support off-line job.
Error message
'%s' source don't support off-line job.
What it means
Thrown by FactoryUtil.ensureJobModeMatch when a BATCH-mode job is configured to use a source whose Boundedness is UNBOUNDED (streaming-only). The library validates that the declared job mode matches the source's capabilities before creating the source reader, since an unbounded source can never finish a batch job.
Source
Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/table/factory/FactoryUtil.java:491
}
try {
virtualCreator.accept(factory.get());
} catch (Exception e) {
if (e instanceof UnsupportedOperationException
&& "The Factory has not been implemented and the deprecated Plugin will be used."
.equals(e.getMessage())) {
return true;
}
log.debug(ExceptionUtils.getMessage(e));
}
return false;
}
public static void ensureJobModeMatch(JobContext jobContext, SeaTunnelSource source) {
if (jobContext.getJobMode() == JobMode.BATCH
&& source.getBoundedness()
== org.apache.seatunnel.api.source.Boundedness.UNBOUNDED) {
throw new UnsupportedOperationException(
String.format(
"'%s' source don't support off-line job.", source.getPluginName()));
}
}
}
View on GitHub (pinned to cf67b549a7)
Solutions
- Switch the job to streaming: set env { job.mode = "STREAMING" } in the config.
- Replace the source with a bounded connector that supports batch mode (e.g. JDBC, file, FakeSource).
- If the connector supports both, configure its startup/stop mode so it reports Boundedness.BOUNDED (e.g. Kafka consumer with a stop offset / specific timestamp).
- Check the connector documentation for which job modes its factory supports before submitting.
Example fix
// before
env { job.mode = "BATCH" }
source { Kafka { ... } }
// after
env { job.mode = "STREAMING" }
source { Kafka { ... } } Defensive patterns
Strategy: validation
Validate before calling
if (jobContext.getJobMode() == JobMode.BATCH && source.getBoundedness() == Boundedness.UNBOUNDED) { throw new IllegalArgumentException("use STREAMING mode or a bounded source"); } Type guard
boolean supportsBatch = source.getBoundedness() == Boundedness.BOUNDED;
Prevention
- Match job.mode to the connector's documented boundedness before submitting
- Check connector docs for supported job modes
- Test batch/streaming configs separately in CI
When it happens
Trigger: Calling SeaTunnelSource/FactoryUtil source creation path with a JobContext whose jobMode is JobMode.BATCH while source.getBoundedness() returns Boundedness.UNBOUNDED — e.g. running a Kafka/CDC source in a batch config ('env { job.mode = "BATCH" }') via a factory that only exposes the unbounded variant.
Common situations: Users write a batch-mode HOCON config but pick a streaming-only connector (Kafka, CDC/MySQL binlog, Pulsar stream); or upgrade a connector that changed its default boundedness; or reuse a streaming job template and only change job.mode to BATCH.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- CONFIGURATION_FAILED
- MqttConnectorErrorCode.INVALID_CONFIG
- UNSUPPORTED_OPERATION
- Schema config can not be empty
- Can not find catalog table with factoryId [%s]
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/28c79b073ffc6514.
Report an issue: GitHub.