commaai/openpilot · critical · RuntimeError
ROM flash command {cdb[0]:02x} {cdb[1]:02x} failed
Error message
ROM flash command {cdb[0]:02x} {cdb[1]:02x} failed What it means
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).
Source
Thrown at openpilot/system/hardware/chestnut/flash.py:385
buf = ctypes.create_string_buffer(bytes(payload), len(payload))
fcntl.ioctl(fd, USBDEVFS_BULK, Bulk(ep, len(payload), timeout, ctypes.cast(buf, ctypes.c_void_p)))
return buf.raw
def cmd(cdb, data=b"", timeout=30000):
nonlocal tag
tag += 1
bulk(0x02, struct.pack("<IIIBBB16s", 0x43425355, tag, len(data), 0, 0, len(cdb), cdb), timeout)
if data:
bulk(0x02, data, timeout)
try:
csw = bulk(0x81, bytes(13), timeout)
except OSError as e:
if e.errno != errno.EPIPE:
raise
fcntl.ioctl(fd, USBDEVFS_CLEAR_HALT, struct.pack("I", 0x81))
csw = bulk(0x81, bytes(13), timeout)
if csw[:4] != b"USBS" or csw[12] != 0:
raise RuntimeError(f"ROM flash command {cdb[0]:02x} {cdb[1]:02x} failed")
print("recovering from the ROM bootloader", flush=True)
try:
cmd(struct.pack(">BBB12x", 0xE1, 0x50, 0), config[:0x80])
cmd(struct.pack(">BBB12x", 0xE1, 0x50, 1), config[0x80:])
cmd(struct.pack(">BBI", 0xE3, 0x50, min(len(image), 0xFF00)), image[:0xFF00])
if len(image) > 0xFF00:
cmd(struct.pack(">BBI", 0xE3, 0xD0, len(image) - 0xFF00), image[0xFF00:])
cmd(struct.pack(">BB13x", 0xE8, 0x51))
finally:
os.close(fd)
print("recovery flash done", flush=True)
def vbus_write(value):
try:
with open(VBUS_PATH, "w") as f:
f.write(value + "\n")View on GitHub (pinned to 516ec1e682)
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
Defensive patterns
Strategy: retry
Validate before calling
from flash import validate_image, find_chestnut validate_image(image) # reject malformed images before ROM mode assert find_chestnut()[0] is not None # device present before recovery
Try / catch
try:
rom_write(image, config)
except RuntimeError as e:
if 'ROM flash command' in str(e):
stabilize_link() # reseat cable, direct port
rom_write(image, config) # full restart is safe - image rewritten from scratch Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- chestnut fell back to the ROM bootloader
- chestnut disappeared before recovery
- chestnut did not re-enumerate after reset
- flash did not converge within {FLASH_BUDGET:g}s
- expected one chestnut, found {len(found)}
AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15).
Data as JSON: /api/errors/e4656169e7a4b830.
Report an issue: GitHub.