{"record":{"id":"7a5fff2f86007035","repo":"nodejs/node","slug":"retried-too-often-giving-up-reason-s","errorCode":null,"errorMessage":"Retried too often. Giving up. Reason: %s","messagePattern":"Retried too often\\. Giving up\\. Reason: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"deps/v8/tools/release/common_includes.py","lineNumber":379,"sourceCode":"                True if the function should be retried. A function throwing an\n                exception is always retried.\n      wait_plan: A list of waiting delays between retries in seconds. The\n                 maximum number of retries is len(wait_plan).\n    \"\"\"\n    retry_on = retry_on or (lambda x: False)\n    wait_plan = list(wait_plan or [])\n    wait_plan.reverse()\n    while True:\n      got_exception = False\n      try:\n        result = cb()\n      except NoRetryException as e:\n        raise e\n      except Exception as e:\n        got_exception = e\n      if got_exception or retry_on(result):\n        if not wait_plan:  # pragma: no cover\n          raise Exception(\"Retried too often. Giving up. Reason: %s\" %\n                          str(got_exception))\n        wait_time = wait_plan.pop()\n        print(\"Waiting for %f seconds.\" % wait_time)\n        self._side_effect_handler.Sleep(wait_time)\n        print(\"Retrying...\")\n      else:\n        return result\n\n  def ReadLine(self, default=None):\n    # Don't prompt in forced mode.\n    if self._options.force_readline_defaults and default is not None:\n      print(\"%s (forced)\" % default)\n      return default\n    else:\n      return self._side_effect_handler.ReadLine()\n\n  def Command(self, name, args, cwd=None):\n    cmd = lambda: self._side_effect_handler.Command(","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/v8/tools/release/common_includes.py#L361-L397","documentation":"Retry repeatedly calls cb, sleeping per the wait_plan backoff schedule, until either cb succeeds (and retry_on(result) is False) or wait_plan is exhausted. When the plan runs out while still failing/retrying, Retry raises a generic Exception whose message embeds the last failure as the Reason.","triggerScenarios":"A transient operation (git, HTTP fetch, etc.) keeps failing across every slot in wait_plan.","commonSituations":"Network down for the whole retry window; git remote unreachable; trybot/buildbucket query consistently erroring; flaky endpoint that doesn't recover in time.","solutions":["Read str(got_exception) in the message — that is the real underlying failure to fix.","Address the root cause (network, auth, remote availability).","If the failure is genuinely transient, pass a longer wait_plan.","For non-retryable failures, raise NoRetryException from cb to abort immediately instead of exhausting the plan."],"exampleFix":"// before\nself.Retry(cb, retry_on=lambda r: not r, [5])\n// after (fail fast on permanent errors)\ndef safe_cb():\n    try: return cb()\n    except PermanentError as e: raise NoRetryException(e)\nself.Retry(safe_cb, retry_on=lambda r: not r, [5, 30])","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = self.Retry(cb, retry_on, wait_plan)\nexcept Exception as e:\n    # The message embeds the last failure; surface it, don't mask it.\n    log.error('Retry exhausted: %s', e)\n    raise","preventionTips":["Raise NoRetryException from cb for permanent failures so you don't burn the whole wait_plan.","Size wait_plan to the realistic recovery time of the dependency.","Log the underlying exception, not just the wrapped message."],"tags":["retry","release-tools","v8","resilience","error-handling"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}