{"record":{"id":"301f5653fa85bdf8","repo":"apache/beam","slug":"num-retries-parameter-cannot-exceed-10000","errorCode":null,"errorMessage":"num_retries parameter cannot exceed 10000.","messagePattern":"num_retries parameter cannot exceed 10000\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/utils/retry.py","lineNumber":102,"sourceCode":"    max_delay_secs: Maximum delay (in seconds). After this limit is reached,\n      further tries use max_delay_sec instead of exponentially increasing\n      the time. Defaults to 1 hour.\n    stop_after_secs: Places a limit on the sum of intervals returned (in\n      seconds), such that the sum is <= stop_after_secs. Defaults to disabled\n      (None). You may need to increase num_retries to effectively use this\n      feature.\n  \"\"\"\n  def __init__(\n      self,\n      initial_delay_secs,\n      num_retries,\n      factor=2,\n      fuzz=0.5,\n      max_delay_secs=60 * 60 * 1,\n      stop_after_secs=None):\n    self._initial_delay_secs = initial_delay_secs\n    if num_retries > 10000:\n      raise ValueError('num_retries parameter cannot exceed 10000.')\n    self._num_retries = num_retries\n    self._factor = factor\n    if not 0 <= fuzz <= 1:\n      raise ValueError('fuzz parameter expected to be in [0, 1] range.')\n    self._fuzz = fuzz\n    self._max_delay_secs = max_delay_secs\n    self._stop_after_secs = stop_after_secs\n\n  def __iter__(self):\n    current_delay_secs = min(self._max_delay_secs, self._initial_delay_secs)\n    total_delay_secs = 0\n    for _ in range(self._num_retries):\n      fuzz_multiplier = 1 - self._fuzz + random.random() * self._fuzz\n      delay_secs = current_delay_secs * fuzz_multiplier\n      total_delay_secs += delay_secs\n      if (self._stop_after_secs is not None and\n          total_delay_secs > self._stop_after_secs):\n        break","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/utils/retry.py#L84-L120","documentation":"retry.FallbackFn/WithFixedDelay-style retry guard validates its configuration in __init__. A num_retries above 10000 is rejected with ValueError to prevent effectively-infinite retry loops with unbounded cumulative backoff.","triggerScenarios":"Constructing a retry guard (e.g. retry.WithFixedDelay or FallbackFn config) with num_retries > 10000, or computing num_retries from a formula that overflows the intended value.","commonSituations":"Typos like num_retries=100000 meaning 10000; passing 'infinite retry' by huge number instead of using stop_after_secs; unit confusion (attempts vs loops).","solutions":["Lower num_retries to <= 10000","Use stop_after_secs to bound retries by time instead of an extreme attempt count","Check where the value is computed/parsed from config for a multiplication or parsing bug"],"exampleFix":"// before\nretry.WithFixedDelay(1, 60, num_retries=100000)\n// after\nretry.WithFixedDelay(1, 60, num_retries=100, stop_after_secs=3600)","handlingStrategy":"validation","validationCode":"if num_retries > 10000:\n    raise ValueError('num_retries must be <= 10000')","typeGuard":null,"tryCatchPattern":"try:\n    guard = retry.WithFixedDelay(1, 60, num_retries=n)\nexcept ValueError as e:\n    logging.error('bad retry config: %s', e)\n    guard = retry.WithFixedDelay(1, 60, num_retries=100)","preventionTips":["Bound retries by time with stop_after_secs rather than huge counts","Validate retry settings read from config files","Keep num_retries within documented limits (<= 10000)"],"tags":["retry","validation","config"],"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"}