commaai/openpilot · error · URLFileException

Remote file is empty or doesn't exist: {self._url}

Error message

Remote file is empty or doesn't exist: {self._url}

What it means

read_aux() with no length argument needs the total file size; get_length() returns -1 when the server's HEAD gives no useful content-length or a non-2xx, and read_aux turns that into 'Remote file is empty or doesn't exist'. So either the URL 404s or the server refuses to report size.

Source

Thrown at openpilot/tools/lib/url_file.py:158

        with atomic_write(full_path, mode="wb", overwrite=True) as new_cached_file:
          new_cached_file.write(data)
        prune_cache(file_name)
      else:
        with open(full_path, "rb") as cached_file:
          data = cached_file.read()

      response += data[max(0, file_begin - position): min(CHUNK_SIZE, file_end - position)]

      position += CHUNK_SIZE
      if position >= file_end:
        self._pos = file_end
        return response

  def read_aux(self, ll: int | None = None) -> bytes:
    if ll is None:
      length = self.get_length()
      if length == -1:
        raise URLFileException(f"Remote file is empty or doesn't exist: {self._url}")
      end = length
    else:
      end = self._pos + ll
    data = self.get_multi_range([(self._pos, end)])
    self._pos += len(data[0])
    return data[0]

  def get_multi_range(self, ranges: list[tuple[int, int]]) -> list[bytes]:
    # HTTP range requests are inclusive
    assert all(e > s for s, e in ranges), "Range end must be greater than start"
    rs = [f"{s}-{e-1}" for s, e in ranges if e > s]

    r = self._request("GET", self._url, headers={"Range": "bytes=" + ",".join(rs)})
    if r.status not in [200, 206]:
      raise URLFileException(f"Expected 206 or 200 response {r.status} ({self._url})")

    ctype = (r.headers.get("content-type") or "").lower()
    if "multipart/byteranges" not in ctype:

View on GitHub (pinned to 516ec1e682)

Solutions

  1. curl -I the URL to see the status and Content-Length
  2. If the link is a presigned URL, regenerate it (they expire)
  3. Read with an explicit byte length (read(ll)) if the size is known from elsewhere, avoiding the HEAD dependency

Example fix

# before
data = URLFile(url).read()

# after
uf = URLFile(url)
length = uf.get_length_online()
if length <= 0:
    raise FileNotFoundError(url)
data = uf.read(length)
Defensive patterns

Strategy: validation

Validate before calling

length = URLFile(url).get_length_online()
if length <= 0:
    raise FileNotFoundError(url)  # or refresh the URL / skip

Try / catch

from openpilot.tools.lib.url_file import URLFileException
try:
    data = URLFile(url).read()
except URLFileException as e:
    if 'empty or doesn' in str(e):
        url = refresh_presigned_url(url)  # expired link
        data = URLFile(url).read()

Prevention

When it happens

Trigger: URLFile(url).read() (whole-file read) against a URL that returns 404/410, a pre-signed URL that expired, or a server that omits Content-Length on HEAD.

Common situations: Expired/rotated CDN links; route files purged from the backend; mis-pasted URL; servers behind config that strips HEAD handling.

Related errors


AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15). Data as JSON: /api/errors/2e3da00361897f56. Report an issue: GitHub.