commaai/openpilot · error · ValueError
start index must be greater than zero
Error message
start index must be greater than zero
What it means
require_nal_unit_start() validates that dat[nal_unit_start:] begins with a NAL start code; it first requires the index itself to be >= 1 because a start code is at least one byte in and index 0 would be ambiguous with the reader's assumptions. Violating that precondition raises ValueError immediately.
Source
Thrown at openpilot/tools/lib/vidindex.py:152
elif prefix_val == 0:
prefix_val = (dat[i] >> j) & 1
prefix_len += 1
else:
suffix_val = (suffix_val << 1) | ((dat[i] >> j) & 1)
suffix_len += 1
j -= 1
if prefix_val == 1 and prefix_len - 1 == suffix_len:
val = int(2**(prefix_len-1) - 1 + suffix_val)
size = prefix_len + suffix_len
return val, size
i += 1
raise VideoFileInvalid("invalid exponential-golomb code")
def require_nal_unit_start(dat: bytes, nal_unit_start: int) -> None:
if nal_unit_start < 1:
raise ValueError("start index must be greater than zero")
if dat[nal_unit_start:nal_unit_start + NAL_UNIT_START_CODE_SIZE] != NAL_UNIT_START_CODE:
raise VideoFileInvalid("data must begin with start code")
def get_hevc_nal_unit_length(dat: bytes, nal_unit_start: int) -> int:
try:
pos = dat.index(NAL_UNIT_START_CODE, nal_unit_start + NAL_UNIT_START_CODE_SIZE)
except ValueError:
pos = -1
# length of NAL unit is byte count up to next NAL unit start index
nal_unit_len = (pos if pos != -1 else len(dat)) - nal_unit_start
if DEBUG:
print(" nal_unit_len:", nal_unit_len)
return nal_unit_len
def get_hevc_nal_unit_type(dat: bytes, nal_unit_start: int) -> HevcNalUnitType:
# 7.3.1.2 NAL unit header syntaxView on GitHub (pinned to 516ec1e682)
Solutions
- Pass an index >= 1 pointing at a real start code (result of dat.find(b'\x00\x00\x00\x01', 1) or similar)
- Guard .find()/index() results: treat -1 and 0 as 'no start code here' before calling
- If your stream truly starts at byte 0, prepend nothing — reconsider: annex-B streams always have the start code at 0, so use a different entry point for that case
Example fix
# before
require_nal_unit_start(dat, dat.find(NAL_UNIT_START_CODE)) # -1 or 0 possible
# after
pos = dat.find(NAL_UNIT_START_CODE, 1)
if pos >= 1:
require_nal_unit_start(dat, pos) Defensive patterns
Strategy: validation
Validate before calling
NAL_UNIT_START_CODE = b'\x00\x00\x00\x01'
pos = dat.find(NAL_UNIT_START_CODE, 1)
if pos >= 1:
require_nal_unit_start(dat, pos) Type guard
def is_valid_nal_start_idx(dat: bytes, i: int) -> bool:
return isinstance(i, int) and i >= 1 and dat[i:i+4] == b'\x00\x00\x00\x01' Prevention
- Never pass 0 or a raw .find() result (-1) as nal_unit_start
- Search for the start code with a start offset of 1
- Unit-test parsers against known-good HEVC headers
When it happens
Trigger: Calling require_nal_unit_start(dat, 0) or with a negative index. Internally, callers pass indices found via searching for start codes, so hitting it externally usually means passing a hand-computed offset of 0.
Common situations: Custom parsing code that assumes the first NAL starts at byte 0; off-by-one when scanning for 00 00 00 01 patterns; negative index from a failed .find() (returns -1).
Related errors
- invalid exponential-golomb code
- data must begin with start code
- data to short to contain nal unit header
- slice_type must be 0, 1, or 2
- data is too short
AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15).
Data as JSON: /api/errors/63f52e79c44cdadc.
Report an issue: GitHub.