commaai/openpilot · error · URLFileException
Expected {len(ranges)} parts, got {len(parts)} ({self._url})
Error message
Expected {len(ranges)} parts, got {len(parts)} ({self._url}) What it means
After splitting a multipart/byteranges response by boundary, url_file counts the payload parts; if the count differs from the number of requested ranges it raises. Causes: server coalesced/dropped ranges, malformed boundaries causing over-splitting, or a 200 full-file response on a multipart content-type.
Source
Thrown at openpilot/tools/lib/url_file.py:192
ctype = (r.headers.get("content-type") or "").lower()
if "multipart/byteranges" not in ctype:
return [r.data,]
m = re.search(r'boundary="?([^";]+)"?', ctype)
if not m:
raise URLFileException(f"Missing multipart boundary ({self._url})")
boundary = m.group(1).encode()
parts = []
for chunk in r.data.split(b"--" + boundary):
if b"\r\n\r\n" not in chunk:
continue
payload = chunk.split(b"\r\n\r\n", 1)[1].rstrip(b"\r\n")
if payload and payload != b"--":
parts.append(payload)
if len(parts) != len(ranges):
raise URLFileException(f"Expected {len(ranges)} parts, got {len(parts)} ({self._url})")
return parts
def seekable(self) -> bool:
return True
def seek(self, pos: int, whence: int = 0) -> int:
pos = int(pos)
if whence == os.SEEK_SET:
self._pos = pos
elif whence == os.SEEK_CUR:
self._pos += pos
elif whence == os.SEEK_END:
length = self.get_length()
assert length != -1, "Cannot seek from end on unknown length file"
self._pos = length + pos
else:
raise URLFileException("Invalid whence value")
return self._posView on GitHub (pinned to 516ec1e682)
Solutions
- Fall back to one range per request (list of single-range calls) — most robust across servers
- Verify each requested range satisfies s<e and ranges don't overlap
- Compare raw response bytes with curl -H 'Range: bytes=0-1,5-6' to see what the server actually returns
Example fix
# before
parts = uf.get_multi_range(ranges)
# after
from openpilot.tools.lib.url_file import URLFileException
try:
parts = uf.get_multi_range(ranges)
except URLFileException:
parts = [uf.get_multi_range([r])[0] for r in ranges] Defensive patterns
Strategy: fallback
Try / catch
try:
parts = uf.get_multi_range(ranges)
except URLFileException as e:
if 'parts, got' in str(e):
parts = [uf.get_multi_range([r])[0] for r in ranges] Prevention
- Ensure ranges are sorted, non-overlapping, and satisfy start < end
- Prefer single-range requests unless the server is known-compliant
- Validate part counts defensively when parsing multipart yourself
When it happens
Trigger: get_multi_range() with N>1 ranges where the server returns fewer/more parts than requested, or boundary bytes appearing inside payload data causing spurious splits.
Common situations: Non-compliant proxies/CDNs rewriting ranged responses; overlapping or zero-width ranges after the e>s filter; servers that answer multi-range requests with only the first range.
Related errors
- Missing multipart boundary ({self._url})
- Failed to {method} {url}: {e}
- Remote file is empty or doesn't exist: {self._url}
- Expected 206 or 200 response {r.status} ({self._url})
- {error_prefix} failed: {reason}/{subject} - {sd.get('message
AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15).
Data as JSON: /api/errors/eee54151f360d4ae.
Report an issue: GitHub.