{"record":{"id":"63f52e79c44cdadc","repo":"commaai/openpilot","slug":"start-index-must-be-greater-than-zero","errorCode":null,"errorMessage":"start index must be greater than zero","messagePattern":"start index must be greater than zero","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"openpilot/tools/lib/vidindex.py","lineNumber":152,"sourceCode":"      elif prefix_val == 0:\n        prefix_val = (dat[i] >> j) & 1\n        prefix_len += 1\n      else:\n        suffix_val = (suffix_val << 1) | ((dat[i] >> j) & 1)\n        suffix_len += 1\n      j -= 1\n\n      if prefix_val == 1 and prefix_len - 1 == suffix_len:\n        val = int(2**(prefix_len-1) - 1 + suffix_val)\n        size = prefix_len + suffix_len\n        return val, size\n    i += 1\n\n  raise VideoFileInvalid(\"invalid exponential-golomb code\")\n\ndef require_nal_unit_start(dat: bytes, nal_unit_start: int) -> None:\n  if nal_unit_start < 1:\n    raise ValueError(\"start index must be greater than zero\")\n\n  if dat[nal_unit_start:nal_unit_start + NAL_UNIT_START_CODE_SIZE] != NAL_UNIT_START_CODE:\n    raise VideoFileInvalid(\"data must begin with start code\")\n\ndef get_hevc_nal_unit_length(dat: bytes, nal_unit_start: int) -> int:\n  try:\n    pos = dat.index(NAL_UNIT_START_CODE, nal_unit_start + NAL_UNIT_START_CODE_SIZE)\n  except ValueError:\n    pos = -1\n\n  # length of NAL unit is byte count up to next NAL unit start index\n  nal_unit_len = (pos if pos != -1 else len(dat)) - nal_unit_start\n  if DEBUG:\n    print(\"  nal_unit_len:\", nal_unit_len)\n  return nal_unit_len\n\ndef get_hevc_nal_unit_type(dat: bytes, nal_unit_start: int) -> HevcNalUnitType:\n  # 7.3.1.2 NAL unit header syntax","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/commaai/openpilot/blob/516ec1e68203439a73f340f1d0b3b91eabc626ee/openpilot/tools/lib/vidindex.py#L134-L170","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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"],"exampleFix":"# before\nrequire_nal_unit_start(dat, dat.find(NAL_UNIT_START_CODE))  # -1 or 0 possible\n\n# after\npos = dat.find(NAL_UNIT_START_CODE, 1)\nif pos >= 1:\n    require_nal_unit_start(dat, pos)","handlingStrategy":"validation","validationCode":"NAL_UNIT_START_CODE = b'\\x00\\x00\\x00\\x01'\npos = dat.find(NAL_UNIT_START_CODE, 1)\nif pos >= 1:\n    require_nal_unit_start(dat, pos)","typeGuard":"def is_valid_nal_start_idx(dat: bytes, i: int) -> bool:\n    return isinstance(i, int) and i >= 1 and dat[i:i+4] == b'\\x00\\x00\\x00\\x01'","tryCatchPattern":null,"preventionTips":["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"],"tags":["video","hevc","api-misuse","vidindex"],"backgroundTag":null,"analyzedSha":"516ec1e68203439a73f340f1d0b3b91eabc626ee","analyzedAt":"2026-08-15T00:17:37.461Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}