{"record":{"id":"2e9d95542a994a50","repo":"apache/beam","slug":"need-to-set-either-the-topic-or-the-subscription-for-a","errorCode":null,"errorMessage":"Need to set either the topic or the subscription for a PubsubIO.Read transform","messagePattern":"Need to set either the topic or 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":1224,"sourceCode":"    /** Enable validation of the PubSub Read. */\n    public Read<T> withValidation() {\n      return toBuilder().setValidate(true).build();\n    }\n\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());","sourceCodeStart":1206,"sourceCodeEnd":1242,"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#L1206-L1242","documentation":"The Read transform's expand() validates its configuration before applying: a PubsubIO.Read must have exactly one source. If neither topic nor subscription was set, this IllegalStateException is thrown during pipeline expansion.","triggerScenarios":"Building PubsubIO.read...() and applying it without ever calling fromTopic(...) or fromSubscription(...) — e.g. conditionally setting the source from config where both branches were skipped.","commonSituations":"Configuration file missing the topic/subscription key; code path where the setter call was commented out or guarded by a false condition.","solutions":["Call .fromTopic(\"projects/P/topics/T\") or .fromSubscription(\"projects/P/subscriptions/S\") on the Read transform before applying.","Check that your config/argument actually contains the topic or subscription value and that the setter isn't skipped on some code path.","Validate configuration at pipeline start so missing source fails early with a clear message."],"exampleFix":"// before\nPubsubIO<String> read = PubsubIO.readStrings();\nif (cfg.useTopic) read = read.fromTopic(cfg.topic); // useTopic false -> nothing set\n// after\ncheckArgument(cfg.topic != null || cfg.subscription != null, \"topic or subscription required\");\nPubsubIO<String> read = cfg.subscription == null\n    ? PubsubIO.readStrings().fromTopic(cfg.topic)\n    : PubsubIO.readStrings().fromSubscription(cfg.subscription);","handlingStrategy":"validation","validationCode":"checkArgument(topic != null || subscription != null,\n    \"PubsubIO.Read requires topic or subscription\");\nPubsubIO.Read<String> read = subscription != null\n    ? PubsubIO.readStrings().fromSubscription(subscription)\n    : PubsubIO.readStrings().fromTopic(topic);","typeGuard":"boolean hasSource(String topic, String subscription) {\n  return topic != null ^ subscription != null; // exactly one\n}","tryCatchPattern":"try {\n  return pipeline.apply(read);\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"Need to set either the topic or the subscription\"))\n    throw new ConfigException(\"No Pub/Sub source configured; set topic or subscription\", e);\n  throw e;\n}","preventionTips":["Fail fast on missing topic/subscription in config parsing","Make one of topic/subscription a required pipeline option","Add a startup validation step before graph expansion"],"tags":["java","pubsub","configuration","beam"],"backgroundTag":"missing-required-argument","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"}