{"record":{"id":"4c85765b4dec7d55","repo":"apache/seatunnel","slug":"airtable-source-connector-not-support-unbounded-op","errorCode":null,"errorMessage":"Airtable source connector not support unbounded operation","messagePattern":"Airtable source connector not support unbounded operation","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-http/connector-http-airtable/src/main/java/org/apache/seatunnel/connectors/seatunnel/airtable/source/AirtableSource.java","lineNumber":70,"sourceCode":"            info.setUsePlaceholderReplacement(false);\n            // Avoid NPE in HttpSourceReader.updateRequestParam for cursor pagination\n            // (pageIndex is unused for cursor mode but referenced defensively).\n            info.setPageIndex(0L);\n            this.pageInfo = info;\n        }\n    }\n\n    @Override\n    public String getPluginName() {\n        return PLUGIN_NAME;\n    }\n\n    @Override\n    public Boundedness getBoundedness() {\n        if (JobMode.BATCH.equals(jobContext.getJobMode())) {\n            return Boundedness.BOUNDED;\n        }\n        throw new UnsupportedOperationException(\n                \"Airtable source connector not support unbounded operation\");\n    }\n\n    @Override\n    public AbstractSingleSplitReader<SeaTunnelRow> createReader(\n            SingleSplitReaderContext readerContext) throws Exception {\n        return new AirtableSourceReader(\n                airtableSourceParameter,\n                readerContext,\n                deserializationSchema,\n                jsonField,\n                contentField,\n                pageInfo,\n                requestIntervalMs,\n                rateLimitBackoffMs,\n                rateLimitMaxRetries);\n    }\n}","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-http/connector-http-airtable/src/main/java/org/apache/seatunnel/connectors/seatunnel/airtable/source/AirtableSource.java#L52-L88","documentation":"AirtableSource.getBoundedness returns BOUNDED only for BATCH jobs and throws UnsupportedOperationException for any unbounded (streaming) job, because the Airtable source can only read a table snapshot once. Streaming (unbounded) execution is not supported by design.","triggerScenarios":"Submitting a job with 'env { mode = \"streaming\" }' (or job.mode=STREAMING) that uses the Airtable source connector.","commonSituations":"Users who want continuous Airtable sync in streaming mode; copy-pasting a streaming job template while swapping in the Airtable source.","solutions":["Set job mode to batch: env { job.mode = \"BATCH\" } in the config.","Schedule the batch job periodically (cron/airflow) to emulate continuous sync.","Use a different connector that supports streaming if incremental sync is required."],"exampleFix":"// before\nenv { job.mode = \"STREAMING\" }\n// after\nenv { job.mode = \"BATCH\" }","handlingStrategy":"validation","validationCode":"// Hocon check before submit\n// env { job.mode = \"BATCH\" }  # required for the Airtable source","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set job.mode = BATCH with the Airtable source","Use a scheduler for periodic sync instead of streaming","Review connector docs for supported boundedness before choosing job mode"],"tags":["airtable","streaming","boundedness","unsupported"],"backgroundTag":"unsupported-operation","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}