{"record":{"id":"28c79b073ffc6514","repo":"apache/seatunnel","slug":"s-source-don-t-support-off-line-job","errorCode":null,"errorMessage":"'%s' source don't support off-line job.","messagePattern":"'(.+?)' source don't support off-line job\\.","errorType":"validation","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"seatunnel-api/src/main/java/org/apache/seatunnel/api/table/factory/FactoryUtil.java","lineNumber":491,"sourceCode":"        }\n        try {\n            virtualCreator.accept(factory.get());\n        } catch (Exception e) {\n            if (e instanceof UnsupportedOperationException\n                    && \"The Factory has not been implemented and the deprecated Plugin will be used.\"\n                            .equals(e.getMessage())) {\n                return true;\n            }\n            log.debug(ExceptionUtils.getMessage(e));\n        }\n        return false;\n    }\n\n    public static void ensureJobModeMatch(JobContext jobContext, SeaTunnelSource source) {\n        if (jobContext.getJobMode() == JobMode.BATCH\n                && source.getBoundedness()\n                        == org.apache.seatunnel.api.source.Boundedness.UNBOUNDED) {\n            throw new UnsupportedOperationException(\n                    String.format(\n                            \"'%s' source don't support off-line job.\", source.getPluginName()));\n        }\n    }\n}\n","sourceCodeStart":473,"sourceCodeEnd":497,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-api/src/main/java/org/apache/seatunnel/api/table/factory/FactoryUtil.java#L473-L497","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nenv { job.mode = \"BATCH\" }\nsource { Kafka { ... } }\n// after\nenv { job.mode = \"STREAMING\" }\nsource { Kafka { ... } }","handlingStrategy":"validation","validationCode":"if (jobContext.getJobMode() == JobMode.BATCH && source.getBoundedness() == Boundedness.UNBOUNDED) { throw new IllegalArgumentException(\"use STREAMING mode or a bounded source\"); }","typeGuard":"boolean supportsBatch = source.getBoundedness() == Boundedness.BOUNDED;","tryCatchPattern":null,"preventionTips":["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"],"tags":["job-mode","source-connector","batch","streaming","config"],"backgroundTag":"incompatible-source-type","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}