{"record":{"id":"c1ddb75ed5b5ed2c","repo":"apache/beam","slug":"max-records-per-bundle-must-be-1-got-r","errorCode":null,"errorMessage":"max_records_per_bundle must be >= 1, got %r","messagePattern":"max_records_per_bundle must be >= 1, got %r","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/io/unbounded_source.py","lineNumber":947,"sourceCode":"    max_records_per_bundle: a busy reader self-checkpoints after emitting this\n      many records in one bundle. Must be >= 1. Defaults to 10000.\n    max_read_time_seconds: a busy reader self-checkpoints after this many\n      seconds in one bundle. Must be > 0. Defaults to 10.0. The deadline is\n      checked between records, so a reader that blocks inside ``advance()`` may\n      overrun it; ``max_records_per_bundle`` is the hard backstop.\n\n  The bundle self-checkpoints as soon as either cap is reached.\n  \"\"\"\n  def __init__(\n      self,\n      source: UnboundedSource,\n      poll_interval: float = _DEFAULT_POLL_INTERVAL_SECONDS,\n      max_records_per_bundle: int = _DEFAULT_MAX_RECORDS_PER_BUNDLE,\n      max_read_time_seconds: float = _DEFAULT_MAX_READ_TIME_SECONDS):\n    if not isinstance(source, UnboundedSource):\n      raise TypeError('source must be an UnboundedSource, got %r' % (source, ))\n    if max_records_per_bundle < 1:\n      raise ValueError(\n          'max_records_per_bundle must be >= 1, got %r' %\n          (max_records_per_bundle, ))\n    if max_read_time_seconds <= 0:\n      raise ValueError(\n          'max_read_time_seconds must be > 0, got %r' %\n          (max_read_time_seconds, ))\n    if poll_interval < 0:\n      raise ValueError(\n          'poll_interval must be >= 0, got %r' % (poll_interval, ))\n    super().__init__()\n    self._source = source\n    self._poll_interval = poll_interval\n    self._max_records_per_bundle = max_records_per_bundle\n    self._max_read_time_seconds = max_read_time_seconds\n\n  def expand(self, pbegin):\n    source = self._source\n    output_coder = source.default_output_coder()","sourceCodeStart":929,"sourceCodeEnd":965,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/unbounded_source.py#L929-L965","documentation":"max_records_per_bundle bounds how many records are emitted per bundle; it must be at least 1. The constructor raises ValueError for values below 1 (zero or negative), which would make per-bundle limiting meaningless or cause non-termination.","triggerScenarios":"Initializing the reader with max_records_per_bundle=0 or a negative int, often passed through from config or a CLI flag.","commonSituations":"Using 0 as a sentinel for 'unlimited' (incorrect here); a config default of 0 leaking into the constructor; arithmetic on a batch-size setting yielding 0.","solutions":["Pass an integer >= 1 (e.g. max_records_per_bundle=1000)","Clamp or validate the value at the config layer: max(1, configured_value)","If unlimited reads are desired, set a very large value rather than 0"],"exampleFix":"# before\nreader = Reader(source, max_records_per_bundle=0)\n# after\nreader = Reader(source, max_records_per_bundle=max(1, configured_batch_size))","handlingStrategy":"validation","validationCode":"if int(max_records_per_bundle) < 1:\n    raise ValueError('max_records_per_bundle must be >= 1')","typeGuard":null,"tryCatchPattern":"try:\n    reader = Reader(source, max_records_per_bundle=n)\nexcept ValueError:\n    reader = Reader(source, max_records_per_bundle=1000)  # safe default","preventionTips":["Clamp config-derived values with max(1, value)","Never use 0 as an 'unlimited' sentinel for this setting","Validate batch-size config at load time"],"tags":["python","apache-beam","validation","config"],"backgroundTag":"invalid-config-value","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"}