commaai/openpilot · error · ValueError
wrapped firmware body exceeds {MAX_CODE_SIZE} bytes
Error message
wrapped firmware body exceeds {MAX_CODE_SIZE} bytes What it means
ValueError from validate_image(): the 4-byte little-endian length header at the start of the wrapped image declares a body larger than MAX_CODE_SIZE (0x10000 = 65536 bytes), the capacity of the ASM2464 code region in SPI flash. The flasher refuses to attempt a write that cannot fit.
Source
Thrown at openpilot/system/hardware/chestnut/flash.py:255
def erase_sector(self, addr):
self.write_enable()
self.transaction(0x20, addr)
self.wait_write_done()
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 = 0View on GitHub (pinned to 516ec1e682)
Solutions
- Confirm the file is the correct artifact: it must be the wrapped chestnut image produced by the matching build step, not a raw binary
- If building your own: reduce firmware size below 64KB (strip, optimize for size, remove dead code) and re-wrap with a correct header
- If hand-wrapping, write the header as struct.pack('<I', len(body)) and verify against the validate_image logic
- Check for accidental concatenation or prepended garbage that shifts the header
Example fix
# after (correct wrap)
body = open('fw.bin','rb').read()
assert len(body) <= 0x10000
wrapped = struct.pack('<I', len(body)) + body + b'\xa5' + bytes([sum(body) & 0xFF]) + zlib.crc32(body).to_bytes(4, 'little') Defensive patterns
Strategy: validation
Validate before calling
import struct
def body_len_ok(data: bytes) -> bool:
return len(data) >= 4 and struct.unpack_from('<I', data)[0] <= 0x10000 Try / catch
try:
validate_image(data)
except ValueError as e:
if 'exceeds' in str(e):
fail_build('firmware too large - trim before flashing') Prevention
- Add a size assertion to the firmware build so oversize images fail at build time
- Use release/size-optimized builds for shipped firmware
- Never flash raw binaries that were not produced by the wrapping step
When it happens
Trigger: validate_image(data) where int.from_bytes(data[:4], 'little') > 65536: either the file is not a wrapped chestnut image (random header bytes), or the firmware build genuinely outgrew the 64KB code region.
Common situations: Passing a raw ELF/bin or a different product's firmware whose first 4 bytes look like a huge length; a build regression (bloat, debug build) pushing the body over 64KB; byte-order confusion when constructing the wrapper by hand.
Related errors
- expected one chestnut, found {len(found)}
- wrapped firmware is too short
- invalid wrapped firmware length or magic
- invalid wrapped firmware checksum
- invalid wrapped firmware CRC
AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15).
Data as JSON: /api/errors/ee952845ad8bda7d.
Report an issue: GitHub.