commaai/openpilot · error · DataUnreadableError

{fn} is empty

Error message

{fn} is empty

What it means

Thrown by assert_hvec() when the first 4 bytes of a video file read as zero-length. openpilot's framereader validates each camera file has a readable HEVC header before indexing; a truly empty (0-byte) file fails here. It surfaces as DataUnreadableError, the library's standard signal that route video data cannot be decoded.

Source

Thrown at openpilot/tools/lib/framereader.py:40

    self.capacity = capacity

  def __getitem__(self, key):
    self._cache.move_to_end(key)
    return self._cache[key]

  def __setitem__(self, key, value):
    self._cache[key] = value
    if len(self._cache) > self.capacity:
      self._cache.popitem(last=False)

  def __contains__(self, key):
    return key in self._cache

def assert_hvec(fn: str) -> None:
  with FileReader(fn) as f:
    header = f.read(4)
  if len(header) == 0:
    raise DataUnreadableError(f"{fn} is empty")
  elif header == b"\x00\x00\x00\x01":
    if 'hevc' not in fn:
      raise NotImplementedError(fn)

def decompress_video_data(rawdat, w, h, pix_fmt="rgb24", vid_fmt='hevc', hwaccel="auto", loglevel="info") -> np.ndarray:
  threads = os.getenv("FFMPEG_THREADS", "0")
  args = ["ffmpeg", "-v", loglevel,
          "-threads", threads,
          "-hwaccel", hwaccel,
          "-c:v", "hevc",
          "-vsync", "0",
          "-f", vid_fmt,
          "-flags2", "showall",
          "-i", "pipe:0",
          "-f", "rawvideo",
          "-pix_fmt", pix_fmt,
          "pipe:1"]
  dat = subprocess.check_output(args, input=rawdat)

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Check the file size: ls -l <camera_file> — a 0-byte file is corrupt/truncated, re-download the segment or use another segment
  2. Delete the cached copy and retry so it is re-fetched (cache lives under Paths.download_cache_root())
  3. If reading locally, verify the original device data is intact (the upload itself was bad); use the qcamera stream as a fallback

Example fix

// before
fr = FrameReader('https://useradmin.comma.ai/camera/...')

// after
import os
from openpilot.tools.lib.url_file import URLFile

if URLFile(fn).get_length_online() <= 0:
    print(f'{fn} is empty, skipping segment')
else:
    fr = FrameReader(fn)
Defensive patterns

Strategy: validation

Validate before calling

from openpilot.tools.lib.url_file import URLFile

def file_nonempty(fn: str) -> bool:
    try:
        return URLFile(fn).get_length_online() > 0 if fn.startswith('http') else os.path.getsize(fn) > 0
    except Exception:
        return False

Try / catch

from openpilot.tools.lib.exceptions import DataUnreadableError
try:
    fr = FrameReader(fn)
except DataUnreadableError as e:
    if 'is empty' in str(e):
        skip_segment(fn)  # corrupt/truncated: do not retry

Prevention

When it happens

Trigger: Calling FrameReader (or get_video_index/assert_hvec) on a route camera file whose size is 0 bytes — e.g. a truncated download from the API/cache, an incompletely uploaded segment, or a corrupted local file.

Common situations: Partial downloads in ~/.comma/... or the openpilot cache dir; a dashcam segment that failed to upload fully; pointing framereader at a placeholder or wrong path that happens to exist but is empty.

Related errors


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