commaai/openpilot · error · ValueError

unknown extension {ext}

Error message

unknown extension {ext}

What it means

_LogFileReader derives the compression from the file extension (plus magic-byte fallback). Extensions other than '', '.bz2', '.zst' — e.g. '.gz', '.zip', '.capnp', or a stray suffix — raise ValueError('unknown extension'). This guards against silently misparsing non-log files.

Source

Thrown at openpilot/tools/lib/logreader.py:99

    return self._enum

  def __getattr__(self, name: str):
    if name.startswith("__") and name.endswith("__"):
      return getattr(self, name)
    return getattr(self._evt, name)


class _LogFileReader:
  def __init__(self, fn, only_union_types=False, sort_by_time=False, dat=None):
    self.data_version = None
    self._only_union_types = only_union_types

    ext = None
    if not dat:
      _, ext = os.path.splitext(urllib.parse.urlparse(fn).path)
      if ext not in ('', '.bz2', '.zst'):
        # old rlogs weren't compressed
        raise ValueError(f"unknown extension {ext}")

      with FileReader(fn) as f:
        dat = f.read()

    if ext == ".bz2" or dat.startswith(b'BZh9'):
      dat = bz2.decompress(dat)
    elif ext == ".zst" or dat.startswith(b'\x28\xB5\x2F\xFD'):
      # https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#zstandard-frames
      dat = decompress_stream(dat)

    ents = capnp_log.Event.read_multiple_bytes(dat)

    self._ents = []
    try:
      for e in ents:
        self._ents.append(CachedEventReader(e))
    except capnp.KjException:
      warnings.warn("Corrupted events detected", RuntimeWarning, stacklevel=1)

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Use plain, '.bz2', or '.zst' rlog/qlog files — re-compress with `zstd` if needed
  2. Strip any accidental suffix so the extension is exactly .bz2/.zst or none
  3. To read in-memory data instead, pass the dat= bytes argument, which bypasses extension checking

Example fix

# before
logs = LogReader('segment/rlog.gz')

# after
import gzip, subprocess
raw = gzip.open('segment/rlog.gz').read()
logs = LogReader(None, dat=subprocess.run(['zstd'], input=raw, capture_output=True).stdout)
Defensive patterns

Strategy: validation

Validate before calling

import os, urllib.parse

def valid_log_path(fn: str) -> bool:
    ext = os.path.splitext(urllib.parse.urlparse(fn).path)[1]
    return ext in ('', '.bz2', '.zst')

Try / catch

try:
    logs = LogReader(fn)
except ValueError as e:
    if 'unknown extension' in str(e):
        recompress_to_zst(fn)  # then retry

Prevention

When it happens

Trigger: Calling LogReader('route/rlog.bz2.x') or a path ending in '.gz'/'.zip'/anything unexpected; also URLs whose path has a query-style suffix that urlparse keeps in the extension.

Common situations: Manually recompressed logs (gzip) instead of zstd/bzip2; passing an index file (.py/.json) to LogReader; rename scripts appending suffixes like '.1' or '.bak'.

Related errors


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