{"record":{"id":"21e989760ded4413","repo":"ytdl-org/youtube-dl","slug":"a-network-error-has-occurred","errorCode":null,"errorMessage":"A network error has occurred.","messagePattern":"A network error has occurred\\.","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"warning","filePath":"youtube_dl/extractor/common.py","lineNumber":585,"sourceCode":"\n    def extract(self, url):\n        \"\"\"Extracts URL information and returns it in list of dicts.\"\"\"\n        try:\n            for _ in range(2):\n                try:\n                    self.initialize()\n                    ie_result = self._real_extract(url)\n                    if self._x_forwarded_for_ip:\n                        ie_result['__x_forwarded_for_ip'] = self._x_forwarded_for_ip\n                    return ie_result\n                except GeoRestrictedError as e:\n                    if self.__maybe_fake_ip_and_retry(e.countries):\n                        continue\n                    raise\n        except ExtractorError:\n            raise\n        except compat_http_client.IncompleteRead as e:\n            raise ExtractorError('A network error has occurred.', cause=e, expected=True)\n        except (KeyError, StopIteration) as e:\n            raise ExtractorError('An extractor error has occurred.', cause=e)\n\n    def __maybe_fake_ip_and_retry(self, countries):\n        if (not self.get_param('geo_bypass_country', None)\n                and self._GEO_BYPASS\n                and self.get_param('geo_bypass', True)\n                and not self._x_forwarded_for_ip\n                and countries):\n            country_code = random.choice(countries)\n            self._x_forwarded_for_ip = GeoUtils.random_ipv4(country_code)\n            if self._x_forwarded_for_ip:\n                self.report_warning(\n                    'Video is geo restricted. Retrying extraction with fake IP %s (%s) as X-Forwarded-For.'\n                    % (self._x_forwarded_for_ip, country_code.upper()))\n                return True\n        return False\n","sourceCodeStart":567,"sourceCodeEnd":603,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/common.py#L567-L603","documentation":"Raised by the generic extractor wrapper in InfoExtractor.extract when the underlying HTTP client raises http.client.IncompleteRead while an extractor is running: the server closed the connection before sending the full response body. It is wrapped as an expected ExtractorError with the original exception as cause, so callers can treat it as a transient network condition rather than a bug.","triggerScenarios":"Any webpage/API download during _real_extract where the server (or a proxy/CDN in between) truncates the response — flaky connections, rate-limiting middleboxes that cut transfers, or servers closing keep-alive sockets early.","commonSituations":"Unstable Wi-Fi/VPN, aggressive CDN throttling on video sites, proxy interference, transient server faults. Re-running the same command often succeeds.","solutions":["Retry the extraction (optionally with --retries and --socket-timeout increased).","Disable or change proxies/VPNs that may be truncating responses.","If it is reproducible for one site only, the site's server/CDN is at fault — try later or from a different network.","Update youtube-dl/yt-dlp; HTTP stack hardening (retries around IncompleteRead) improved over versions."],"exampleFix":"from youtube_dl.utils import ExtractorError\nimport http.client\n\nfor attempt in range(3):\n    try:\n        info = ydl.extract_info(url, download=False)\n        break\n    except ExtractorError as e:\n        if isinstance(e.cause, http.client.IncompleteRead) and attempt < 2:\n            continue\n        raise","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"from youtube_dl.utils import ExtractorError\nimport http.client\nfor attempt in range(3):\n    try:\n        info = ydl.extract_info(url, download=False)\n        break\n    except ExtractorError as e:\n        if isinstance(e.cause, http.client.IncompleteRead) and attempt < 2:\n            continue  # transient truncation; retry\n        raise","preventionTips":["Wrap batch jobs with per-URL retry policies for transient network errors.","Set --retries and --socket-timeout generously on flaky links.","Check e.cause to distinguish network truncation from site breakage."],"tags":["network","incomplete-read","transient","retry"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}