{"record":{"id":"d917101574a5e045","repo":"apache/beam","slug":"expected-size-0-but-received-s","errorCode":null,"errorMessage":"Expected size >= 0 but received %s.","messagePattern":"Expected size >= 0 but received (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/runners/common.py","lineNumber":1072,"sourceCode":"    if additional_kwargs:\n      kwargs_for_process.update(additional_kwargs)\n\n    self.output_handler.handle_process_outputs(\n        windowed_value,\n        self.process_method(*args_for_process, **kwargs_for_process),\n        self.threadsafe_watermark_estimator)\n\n    if self.is_splittable:\n      assert self.threadsafe_restriction_tracker is not None\n      self.threadsafe_restriction_tracker.check_done()\n      deferred_status = self.threadsafe_restriction_tracker.deferred_status()\n      if deferred_status:\n        deferred_restriction, deferred_timestamp = deferred_status\n        element = windowed_value.value\n        size = self.signature.get_restriction_provider().restriction_size(\n            element, deferred_restriction)\n        if size < 0:\n          raise ValueError('Expected size >= 0 but received %s.' % size)\n        current_watermark = (\n            self.threadsafe_watermark_estimator.current_watermark())\n        estimator_state = (\n            self.threadsafe_watermark_estimator.get_estimator_state())\n        residual_value = ((element, (deferred_restriction, estimator_state)),\n                          size)\n        return SplitResultResidual(\n            residual_value=windowed_value.with_value(residual_value),\n            current_watermark=current_watermark,\n            deferred_timestamp=deferred_timestamp)\n    return None\n\n  def _invoke_process_batch_per_window(\n      self,\n      windowed_batch: WindowedBatch,\n      additional_args,\n      additional_kwargs,\n  ):","sourceCodeStart":1054,"sourceCodeEnd":1090,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/runners/common.py#L1054-L1090","documentation":"During SDF process invocation with a deferred (truncated) result, Beam computes the restriction's size via restriction_size() and requires it to be non-negative, because size feeds element weighting for splitting and progress. A negative size means the user's RestrictionProvider returned an invalid size, so Beam raises immediately.","triggerScenarios":"A custom RestrictionProvider's restriction_size() returns a negative number while processing deferred/continuation results from a splittable DoFn.","commonSituations":"Custom restriction size functions computing ranges (end-start) that can go negative on malformed restrictions; off-by-one or reversed start/end in a custom RestrictionTracker; division/negation bugs in size estimation.","solutions":["Fix restriction_size() to clamp at 0 (e.g. max(0, end - start))","Validate the restriction invariants (start <= end) in the RestrictionProvider before returning sizes","Check the RestrictionTracker's try_split/current_restriction logic for producing inverted restrictions"],"exampleFix":"# before\ndef restriction_size(self, element, restriction):\n    return restriction.end - restriction.start\n# after\ndef restriction_size(self, element, restriction):\n    return max(0, restriction.end - restriction.start)","handlingStrategy":"validation","validationCode":"def validate_restriction_provider(provider, element, restriction):\n    size = provider.restriction_size(element, restriction)\n    if size < 0:\n        raise ValueError('restriction_size returned %s; clamp to >= 0' % size)\n    return size","typeGuard":"def has_valid_size(provider, element, restriction):\n    return provider.restriction_size(element, restriction) >= 0","tryCatchPattern":"try:\n    process_element(element)\nexcept ValueError as e:\n    if 'Expected size >= 0' in str(e):\n        logging.error('RestrictionProvider produced negative size: %s', e)\n    raise","preventionTips":["Implement restriction_size as max(0, end - start)","Assert restriction.start <= restriction.stop in your RestrictionTracker","Test restriction_size with boundary and degenerate restrictions"],"tags":["apache-beam","python","splittable-dofn","restriction-size"],"backgroundTag":"value-out-of-range","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}