{"record":{"id":"e4656169e7a4b830","repo":"commaai/openpilot","slug":"rom-flash-command-cdb-0-02x-cdb-1-02x-failed","errorCode":null,"errorMessage":"ROM flash command {cdb[0]:02x} {cdb[1]:02x} failed","messagePattern":"ROM flash command (.+?) (.+?) failed","errorType":"console","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"openpilot/system/hardware/chestnut/flash.py","lineNumber":385,"sourceCode":"    buf = ctypes.create_string_buffer(bytes(payload), len(payload))\n    fcntl.ioctl(fd, USBDEVFS_BULK, Bulk(ep, len(payload), timeout, ctypes.cast(buf, ctypes.c_void_p)))\n    return buf.raw\n\n  def cmd(cdb, data=b\"\", timeout=30000):\n    nonlocal tag\n    tag += 1\n    bulk(0x02, struct.pack(\"<IIIBBB16s\", 0x43425355, tag, len(data), 0, 0, len(cdb), cdb), timeout)\n    if data:\n      bulk(0x02, data, timeout)\n    try:\n      csw = bulk(0x81, bytes(13), timeout)\n    except OSError as e:\n      if e.errno != errno.EPIPE:\n        raise\n      fcntl.ioctl(fd, USBDEVFS_CLEAR_HALT, struct.pack(\"I\", 0x81))\n      csw = bulk(0x81, bytes(13), timeout)\n    if csw[:4] != b\"USBS\" or csw[12] != 0:\n      raise RuntimeError(f\"ROM flash command {cdb[0]:02x} {cdb[1]:02x} failed\")\n\n  print(\"recovering from the ROM bootloader\", flush=True)\n  try:\n    cmd(struct.pack(\">BBB12x\", 0xE1, 0x50, 0), config[:0x80])\n    cmd(struct.pack(\">BBB12x\", 0xE1, 0x50, 1), config[0x80:])\n    cmd(struct.pack(\">BBI\", 0xE3, 0x50, min(len(image), 0xFF00)), image[:0xFF00])\n    if len(image) > 0xFF00:\n      cmd(struct.pack(\">BBI\", 0xE3, 0xD0, len(image) - 0xFF00), image[0xFF00:])\n    cmd(struct.pack(\">BB13x\", 0xE8, 0x51))\n  finally:\n    os.close(fd)\n  print(\"recovery flash done\", flush=True)\n\n\ndef vbus_write(value):\n  try:\n    with open(VBUS_PATH, \"w\") as f:\n      f.write(value + \"\\n\")","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/commaai/openpilot/blob/516ec1e68203439a73f340f1d0b3b91eabc626ee/openpilot/system/hardware/chestnut/flash.py#L367-L403","documentation":"RuntimeError from the cmd() helper inside rom_write(): a SCSI BOT (Bulk-Only Transport) command sent to the ROM bootloader returned a Command Status Wrapper whose signature was not 'USBS' or whose status byte (csw[12]) was non-zero - the bootloader rejected or failed the vendor command. The CDB bytes in the message identify the failing recovery step (e.g. 'e3 50' writes firmware block 0, 'e8 51' finalizes).","triggerScenarios":"rom_write()'s sequence: cmd(0xE1,0x50,...) writes config pages, cmd(0xE3,0x50/0xD0,...) writes firmware blocks, cmd(0xE8,0x51) finalizes. Any of these returning a failed CSW raises - caused by corrupt bulk data on a flaky link, a device-side flash write error, a protocol stall the CLEAR_HALT retry did not clear, or malformed image lengths in the CDB.","commonSituations":"Interrupted or corrupt bulk transfer on a bad cable during ROM recovery; a modified script sending chunks longer than the 0xFF00 split the ROM command accepts; flash chip hardware fault; commands sent out of order after a partial earlier failure.","solutions":["Re-run the full recovery - ROM commands rewrite from the start, and a retry with a stable link usually succeeds","Verify the image with validate_image() before recovery so the ROM never gets malformed lengths or data","Move to a direct, high-quality USB connection; recovery uses 30s bulk timeouts, and hubs and long cables are the classic failure source","If the same CDB fails deterministically across retries, the flash chip itself is failing in ROM mode - hardware replacement is the remaining option"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"from flash import validate_image, find_chestnut\n\nvalidate_image(image)                    # reject malformed images before ROM mode\nassert find_chestnut()[0] is not None    # device present before recovery","typeGuard":null,"tryCatchPattern":"try:\n    rom_write(image, config)\nexcept RuntimeError as e:\n    if 'ROM flash command' in str(e):\n        stabilize_link()          # reseat cable, direct port\n        rom_write(image, config)  # full restart is safe - image rewritten from scratch","preventionTips":["Validate the image before entering ROM recovery","Flash recovery on a direct, high-quality USB connection only","If one CDB fails deterministically across retries, classify it as hardware failure and replace the unit"],"tags":["usb","recovery","bootloader","bulk-transfer","scsi-bot","flashing"],"backgroundTag":null,"analyzedSha":"516ec1e68203439a73f340f1d0b3b91eabc626ee","analyzedAt":"2026-08-15T00:17:37.461Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}