commaai/openpilot · error · ValueError

invalid wrapped firmware checksum

Error message

invalid wrapped firmware checksum

What it means

ValueError from validate_image(): the additive checksum byte at offset body_len+5 does not equal sum(body) & 0xFF. The wrapper stores a simple byte-sum checksum of the firmware body; a mismatch means the body bytes were altered after wrapping - corruption in transfer/storage, or a header length that slices the wrong body window.

Source

Thrown at openpilot/system/hardware/chestnut/flash.py:260

  def program(self, addr, data):
    self.write_buffer(data + bytes((-len(data)) % 4))
    self.write_enable()
    self.transaction(0x02, addr, len(data), mode=1)
    self.wait_write_done()


def validate_image(data):
  if len(data) < 10:
    raise ValueError("wrapped firmware is too short")
  body_len = int.from_bytes(data[:4], "little")
  if body_len > MAX_CODE_SIZE:
    raise ValueError(f"wrapped firmware body exceeds {MAX_CODE_SIZE} bytes")
  if len(data) != body_len + 10 or data[4 + body_len] != 0xA5:
    raise ValueError("invalid wrapped firmware length or magic")
  body = data[4:4 + body_len]
  if data[5 + body_len] != sum(body) & 0xFF:
    raise ValueError("invalid wrapped firmware checksum")
  if data[6 + body_len:] != zlib.crc32(body).to_bytes(4, "little"):
    raise ValueError("invalid wrapped firmware CRC")


def image_product(image):
  match = re.search(rb"custom [0-9a-f]{8}-CLEAN", image)
  if match is None:
    raise ValueError("no product string in wrapped firmware")
  return match.group().decode()


def reconnect(flash):
  attempt = 0
  while True:
    attempt += 1
    check_budget()
    try:
      flash.connect()

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Re-download or re-copy the firmware image in binary mode and re-validate
  2. Verify transport integrity with sha256 on both ends before flashing
  3. If building the wrapper yourself, compute the checksum byte as sum(body) & 0xFF after the final body bytes are fixed
  4. If the checksum is wrong, treat it as corruption - recopy the file; do not patch the checksum byte

Example fix

# after (when wrapping)
checksum = sum(body) & 0xFF
wrapped = struct.pack('<I', len(body)) + body + b'\xa5' + bytes([checksum]) + zlib.crc32(body).to_bytes(4, 'little')
Defensive patterns

Strategy: validation

Validate before calling

import struct

def checksum_ok(data: bytes) -> bool:
    if len(data) < 10:
        return False
    body_len = struct.unpack_from('<I', data)[0]
    if len(data) != body_len + 10:
        return False
    return data[5 + body_len] == sum(data[4:4 + body_len]) & 0xFF

Prevention

When it happens

Trigger: validate_image(data) where data[5+body_len] != sum(data[4:4+body_len]) & 0xFF. Produced by any corruption in the body, a wrong body_len header (so the checksummed window is wrong), or a file re-encoded in text mode.

Common situations: scp/ftp in ASCII mode flipping bytes; bit rot or partial writes on the target's storage; mixing header and body from different builds when hand-assembling the wrapper; little-endian vs big-endian header mistakes.

Related errors


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