{"record":{"id":"524886962c5f3ff3","repo":"apache/beam","slug":"can-t-set-both-the-topic-and-the-subscription-for-a-pubsubio","errorCode":null,"errorMessage":"Can't set both the topic and the subscription for a PubsubIO.Read transform","messagePattern":"Can't set both the topic and the subscription for a PubsubIO\\.Read transform","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/pubsub/PubsubIO.java","lineNumber":1228,"sourceCode":"\n    @VisibleForTesting\n    /**\n     * Set's the internal Clock.\n     *\n     * <p>Only for use by unit tests.\n     */\n    Read<T> withClock(Clock clock) {\n      return toBuilder().setClock(clock).build();\n    }\n\n    @Override\n    public PCollection<T> expand(PBegin input) {\n      if (getTopicProvider() == null && getSubscriptionProvider() == null) {\n        throw new IllegalStateException(\n            \"Need to set either the topic or the subscription for \" + \"a PubsubIO.Read transform\");\n      }\n      if (getTopicProvider() != null && getSubscriptionProvider() != null) {\n        throw new IllegalStateException(\n            \"Can't set both the topic and the subscription for \" + \"a PubsubIO.Read transform\");\n      }\n\n      if (getDeadLetterTopicProvider() != null\n          && !(getBadRecordRouter() instanceof ThrowingBadRecordRouter)) {\n        throw new IllegalArgumentException(\n            \"PubSubIO cannot be configured with both a dead letter topic and a bad record router\");\n      }\n\n      ValueProvider<PubsubTopic> topicProvider = getTopicProvider();\n      @Nullable ValueProvider<TopicPath> topicPath =\n          topicProvider == null\n              ? null\n              : NestedValueProvider.of(topicProvider, new TopicPathTranslator());\n      ValueProvider<PubsubSubscription> subscriptionProvider = getSubscriptionProvider();\n      @Nullable ValueProvider<SubscriptionPath> subscriptionPath =\n          subscriptionProvider == null\n              ? null","sourceCodeStart":1210,"sourceCodeEnd":1246,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/pubsub/PubsubIO.java#L1210-L1246","documentation":"Read.expand() enforces mutually exclusive sources: a PubsubIO.Read transform may read from a topic OR a subscription, never both. When both are set, this IllegalStateException is thrown at pipeline construction.","triggerScenarios":"Calling both fromTopic(...) and fromSubscription(...) on the same Read transform — commonly when merging config values or chaining builder calls where each branch sets a different source.","commonSituations":"Config providing both topic and subscription keys and code setting both unconditionally; combining a default builder (with a topic) with a subscription override.","solutions":["Set only one: keep fromSubscription(...) if you want a durable subscription, and remove the fromTopic(...) call.","If both values exist in config, choose with an if/else instead of setting both.","Note topic-vs-subscription semantics differ (subscription tracks acks); pick deliberately."],"exampleFix":"// before\nPubsubIO.readStrings().fromTopic(t).fromSubscription(s);\n// after\nPubsubIO.readStrings().fromSubscription(s); // or fromTopic(t), never both","handlingStrategy":"validation","validationCode":"checkArgument(topic == null || subscription == null,\n    \"Set only one of topic or subscription, not both\");\nPubsubIO.Read<String> read = subscription != null\n    ? PubsubIO.readStrings().fromSubscription(subscription)\n    : PubsubIO.readStrings().fromTopic(topic);","typeGuard":"boolean exactlyOneSource(String topic, String subscription) {\n  return (topic != null) ^ (subscription != null);\n}","tryCatchPattern":"try {\n  return pipeline.apply(read);\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"Can't set both the topic and the subscription\"))\n    throw new ConfigException(\"Provide either topic or subscription, not both\", e);\n  throw e;\n}","preventionTips":["Use if/else (not both) when config carries both keys","Wrap source selection in a single factory method","Validate exactly-one-of constraints before building the pipeline"],"tags":["java","pubsub","configuration","mutually-exclusive","beam"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}