{"record":{"id":"fa80096639325bcb","repo":"commaai/openpilot","slug":"expected-206-or-200-response-r-status-self-ur","errorCode":null,"errorMessage":"Expected 206 or 200 response {r.status} ({self._url})","messagePattern":"Expected 206 or 200 response (.+?) \\((.+?)\\)","errorType":"exception","errorClass":"URLFileException","httpStatus":null,"severity":"error","filePath":"openpilot/tools/lib/url_file.py","lineNumber":173,"sourceCode":"    if ll is None:\n      length = self.get_length()\n      if length == -1:\n        raise URLFileException(f\"Remote file is empty or doesn't exist: {self._url}\")\n      end = length\n    else:\n      end = self._pos + ll\n    data = self.get_multi_range([(self._pos, end)])\n    self._pos += len(data[0])\n    return data[0]\n\n  def get_multi_range(self, ranges: list[tuple[int, int]]) -> list[bytes]:\n    # HTTP range requests are inclusive\n    assert all(e > s for s, e in ranges), \"Range end must be greater than start\"\n    rs = [f\"{s}-{e-1}\" for s, e in ranges if e > s]\n\n    r = self._request(\"GET\", self._url, headers={\"Range\": \"bytes=\" + \",\".join(rs)})\n    if r.status not in [200, 206]:\n      raise URLFileException(f\"Expected 206 or 200 response {r.status} ({self._url})\")\n\n    ctype = (r.headers.get(\"content-type\") or \"\").lower()\n    if \"multipart/byteranges\" not in ctype:\n      return [r.data,]\n\n    m = re.search(r'boundary=\"?([^\";]+)\"?', ctype)\n    if not m:\n      raise URLFileException(f\"Missing multipart boundary ({self._url})\")\n    boundary = m.group(1).encode()\n\n    parts = []\n    for chunk in r.data.split(b\"--\" + boundary):\n      if b\"\\r\\n\\r\\n\" not in chunk:\n        continue\n      payload = chunk.split(b\"\\r\\n\\r\\n\", 1)[1].rstrip(b\"\\r\\n\")\n      if payload and payload != b\"--\":\n        parts.append(payload)\n    if len(parts) != len(ranges):","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/commaai/openpilot/blob/516ec1e68203439a73f340f1d0b3b91eabc626ee/openpilot/tools/lib/url_file.py#L155-L191","documentation":"get_multi_range() issues an HTTP Range request and only accepts 200 (server ignored Range, sent everything) or 206 (partial content). Any other status — 403, 404, 416, 500 — raises immediately. 416 usually means seeking past EOF (bad cached length vs. truncated remote file).","triggerScenarios":"Seeking/reading ranges from a URL whose server returns an error for ranged GET: file deleted mid-session, expired link (403), range beyond file size after the file changed, or a server that disallows ranges and errors instead of returning 200.","commonSituations":"Route file replaced/truncated on the backend while a cached length says it is longer; S3 presigned URL expired; proxy interfering with Range headers.","solutions":["Reproduce with curl -H 'Range: bytes=0-99' <url> to see the actual status","Reset the URLFile length cache / recreate the URLFile so sizes are re-fetched, then retry","If the link expired (403), obtain a fresh URL or re-authenticate"],"exampleFix":"# before\nchunk = uf.get_multi_range([(0, 1024)])\n\n# after\nfrom openpilot.tools.lib.url_file import URLFileException\ntry:\n    chunk = uf.get_multi_range([(0, 1024)])\nexcept URLFileException as e:\n    if '416' in str(e):\n        uf._length = None  # stale cached length\n        chunk = uf.get_multi_range([(0, 1024)])\n    else:\n        raise","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from openpilot.tools.lib.url_file import URLFileException\ntry:\n    parts = uf.get_multi_range(ranges)\nexcept URLFileException as e:\n    status = str(e).split()[3]\n    if status == '416':\n        uf._length = None  # stale size: refetch\n        parts = uf.get_multi_range(ranges)\n    else:\n        raise","preventionTips":["Use fresh URLFile instances after remote files may have changed","Keep requested ranges within a just-fetched length","Map the status code to a remedy: 403 expired link, 404 gone, 416 stale size"],"tags":["network","http","range-request","url-file"],"backgroundTag":null,"analyzedSha":"516ec1e68203439a73f340f1d0b3b91eabc626ee","analyzedAt":"2026-08-15T00:17:37.461Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}