{"record":{"id":"dad2ca0d2cab8d19","repo":"apache/seatunnel","slug":"google-pub-sub-source-expects-exactly-one-source-s","errorCode":null,"errorMessage":"Google Pub/Sub source expects exactly one source split","messagePattern":"Google Pub/Sub source expects exactly one source split","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-google-pubsub/src/main/java/org/apache/seatunnel/connectors/seatunnel/google/pubsub/source/GooglePubSubSourceReader.java","lineNumber":133,"sourceCode":"                        \"Failed to deserialize Google Pub/Sub message \"\n                                + receivedMessage.message.getMessageId(),\n                        e);\n            }\n        }\n    }\n\n    @Override\n    public List<SingleSplit> snapshotState(long checkpointId) {\n        synchronized (acknowledgementLock) {\n            pendingAcknowledgements.put(checkpointId, new ArrayList<>(unacknowledgedMessages));\n        }\n        return Collections.singletonList(new SingleSplit(null));\n    }\n\n    @Override\n    public void addSplits(List<SingleSplit> splits) {\n        if (splits.size() != 1) {\n            throw new IllegalArgumentException(\n                    \"Google Pub/Sub source expects exactly one source split\");\n        }\n        if (splitAssigned) {\n            return;\n        }\n\n        subscriber =\n                subscriberFactory.create(\n                        (message, acknowledgement) ->\n                                receivedMessages.add(new ReceivedMessage(message, acknowledgement)),\n                        failure -> subscriberFailure.compareAndSet(null, failure));\n        subscriber.start();\n        splitAssigned = true;\n    }\n\n    @Override\n    public void handleNoMoreSplits() {\n        // The single subscription split remains active for the lifetime of the streaming job.","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-google-pubsub/src/main/java/org/apache/seatunnel/connectors/seatunnel/google/pubsub/source/GooglePubSubSourceReader.java#L115-L151","documentation":"Thrown from GooglePubSubSourceReader.addSplits when the engine hands the reader a list of source splits whose size is not exactly one. Pub/Sub subscriptions are a single logical stream, so the connector enumerates exactly one SingleSplit; any other number violates the connector's invariant.","triggerScenarios":"addSplits(list) called (via assignSplit) with an empty list or more than one split — typically only possible through custom/test code or an engine/restore path that reassigns snapshots taken from a differently-shaped source.","commonSituations":"Restoring from a checkpoint/savepoint produced by another connector or a modified split enumeration; unit or integration tests feeding synthetic split lists; parallelism/split mishandling in custom engine integrations.","solutions":["Ensure restore state comes from a checkpoint of the same GooglePubSub source version and configuration.","In tests or custom code, always pass a list containing exactly one split (as produced by the split enumerator).","If migrating from an older connector version, start the job fresh rather than restoring incompatible state."],"exampleFix":"// before\nreader.addSplits(Collections.emptyList());\n// after\nreader.addSplits(Collections.singletonList(new SingleSplit(null)));","handlingStrategy":"validation","validationCode":"if (splits == null || splits.size() != 1) {\n    throw new IllegalArgumentException(\"Pass exactly one split to GooglePubSubSourceReader\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    reader.addSplits(splits);\n} catch (IllegalArgumentException e) {\n    logger.error(\"Split invariant violated for Pub/Sub reader\", e);\n    throw e;\n}","preventionTips":["Only restore state from checkpoints of the same connector version.","In tests, build splits with the connector's own enumerator rather than hand-rolled lists."],"tags":["google-pubsub","source-split","state","java"],"backgroundTag":"internal-invariant-violation","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}