{"record":{"id":"d5ddd9ad8b8b3011","repo":"commaai/openpilot","slug":"wrapped-firmware-is-too-short","errorCode":null,"errorMessage":"wrapped firmware is too short","messagePattern":"wrapped firmware is too short","errorType":"console","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"openpilot/system/hardware/chestnut/flash.py","lineNumber":252,"sourceCode":"      for off in range(0, n, 255):\n        out += self.reg_read(0x7000 + off, min(255, n - off))\n    return bytes(out)\n\n  def erase_sector(self, addr):\n    self.write_enable()\n    self.transaction(0x20, addr)\n    self.wait_write_done()\n\n  def program(self, addr, data):\n    self.write_buffer(data + bytes((-len(data)) % 4))\n    self.write_enable()\n    self.transaction(0x02, addr, len(data), mode=1)\n    self.wait_write_done()\n\n\ndef validate_image(data):\n  if len(data) < 10:\n    raise ValueError(\"wrapped firmware is too short\")\n  body_len = int.from_bytes(data[:4], \"little\")\n  if body_len > MAX_CODE_SIZE:\n    raise ValueError(f\"wrapped firmware body exceeds {MAX_CODE_SIZE} bytes\")\n  if len(data) != body_len + 10 or data[4 + body_len] != 0xA5:\n    raise ValueError(\"invalid wrapped firmware length or magic\")\n  body = data[4:4 + body_len]\n  if data[5 + body_len] != sum(body) & 0xFF:\n    raise ValueError(\"invalid wrapped firmware checksum\")\n  if data[6 + body_len:] != zlib.crc32(body).to_bytes(4, \"little\"):\n    raise ValueError(\"invalid wrapped firmware CRC\")\n\n\ndef image_product(image):\n  match = re.search(rb\"custom [0-9a-f]{8}-CLEAN\", image)\n  if match is None:\n    raise ValueError(\"no product string in wrapped firmware\")\n  return match.group().decode()\n","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/commaai/openpilot/blob/516ec1e68203439a73f340f1d0b3b91eabc626ee/openpilot/system/hardware/chestnut/flash.py#L234-L270","documentation":"ValueError from validate_image(): the wrapped firmware file passed for flashing is under 10 bytes total. A valid wrapper is a 4-byte little-endian body length + body + magic byte + checksum byte + 4-byte CRC32, so it can never be shorter than 10 bytes. A file this small is essentially empty, truncated, or the wrong file entirely.","triggerScenarios":"validate_image(data) where data came from FIRMWARE_PATH (firmware_wrapped.bin next to the script) or a user-supplied image: the file is 0-9 bytes - empty placeholder, a failed download, a git-LFS pointer stub, or a text file passed by mistake.","commonSituations":"firmware_wrapped.bin missing from the deployment with an empty file left in its place; a truncated artifact from an interrupted CI download; pointing --image at a README or checksum file instead of the wrapped binary.","solutions":["Check the file with ls -l and file on firmware_wrapped.bin - a real image is roughly 65KB (up to 0x10000 body + 10 bytes wrapper)","Regenerate or re-download the firmware artifact from the build that produces it (the wrapper is created by the packaging step, not hand-made)","If supplying your own image, re-export it; do not hand-edit binaries","Verify the path you pass actually points at the wrapped bin, not an unrelated file"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import os\n\ndef image_plausible(path) -> bool:\n    size = os.path.getsize(path)\n    return 10 <= size <= 10 + 0x10000","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check file size (at least 10 bytes, at most about 64KB + 10) before invoking the flasher","Fetch firmware artifacts atomically (download to temp, rename) so partial files never land at the final path","Keep artifacts under checksummed storage"],"tags":["firmware","validation","file-format"],"backgroundTag":null,"analyzedSha":"516ec1e68203439a73f340f1d0b3b91eabc626ee","analyzedAt":"2026-08-15T00:17:37.461Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}