apache/beam · error · TypeError

Only one of topic and subscription may be specified.

Error message

Only one of topic and subscription may be specified.

What it means

read_from_pubsub validates its arguments: both 'topic' and 'subscription' were given, but a Pub/Sub read binds to exactly one of them; the guard fires at graph construction before any subscription is created.

Source

Thrown at sdks/python/apache_beam/yaml/yaml_io.py:388

      deduplication of messages. If not provided, we cannot guarantee
      that no duplicate data will be delivered on the Pub/Sub stream. In this
      case, deduplication of the stream will be strictly best effort.
    timestamp_attribute: Message value to use as element timestamp. If None,
      uses message publishing time as the timestamp.

      Timestamp values should be in one of two formats:

      - A numerical value representing the number of milliseconds since the
        Unix epoch.
      - A string in RFC 3339 format, UTC timezone. Example:
        ``2015-10-29T23:41:41.123Z``. The sub-second component of the
        timestamp is optional, and digits beyond the first three (i.e., time
        units smaller than milliseconds) may be ignored.
    publish_time_field: Field to add to output messages with the Pub/Sub
      message publish time. If None, no such field is added.
  """
  if topic and subscription:
    raise TypeError('Only one of topic and subscription may be specified.')
  elif not topic and not subscription:
    raise TypeError('One of topic or subscription may be specified.')
  if publish_time_field is not None and not publish_time_field.strip():
    raise ValueError('publish_time_field must be a non-empty field name.')
  has_publish_time_field = publish_time_field is not None
  payload_schema, parser = _create_parser(format, schema)
  extra_fields: list[schema_pb2.Field] = []
  if not attributes and not attributes_map and not has_publish_time_field:
    mapper = lambda msg: parser(msg)
  else:
    if isinstance(attributes, str):
      attributes = [attributes]
    if attributes:
      extra_fields.extend(
          [schemas.schema_field(attr, str) for attr in attributes])
    if attributes_map:
      extra_fields.append(
          schemas.schema_field(attributes_map, Mapping[str, str]))

View on GitHub (pinned to 12126d8942)

Solutions

  1. Specify only the subscription (it already determines the topic)
  2. Or specify only the topic to let Beam create/use an ephemeral path
  3. Remove the redundant key from your YAML/config before calling

Example fix

// before
read_from_pubsub(topic='projects/p/topics/t', subscription='projects/p/subs/s')
// after
read_from_pubsub(subscription='projects/p/subs/s')
Defensive patterns

Strategy: validation

Validate before calling

if bool(topic) and bool(subscription):
    raise ValueError('Pass only one of topic or subscription')

Try / catch

try:
    read_from_pubsub(topic=t, subscription=s)
except TypeError as e:
    if 'Only one of topic' in str(e):
        read_from_pubsub(subscription=s)

Prevention

When it happens

Trigger: Calling read_from_pubsub(topic=..., subscription=...) with both arguments truthy.

Common situations: Config templating fills in both keys; users paste a subscription path while also keeping the topic argument from earlier config.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/0023181661c05881. Report an issue: GitHub.