commaai/openpilot · error · RuntimeError

chestnut disappeared before recovery

Error message

chestnut disappeared before recovery

What it means

RuntimeError at the top of rom_write(): the tool entered ROM-bootloader recovery but find_chestnut() now returns None - the device, which moments ago matched a ROM VID:PID (174c:2464/2463), has vanished from the USB bus before the recovery transfer could start. Recovery cannot proceed without a live ROM-bootloader endpoint.

Source

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

  except FileExistsError as e:
    backup = open(path, "rb").read()
    if len(backup) != 0x100:
      raise RuntimeError(f"invalid config backup: {path}") from e
    if backup != data:
      print(f"restoring config from {path}", flush=True)
    return backup
  with os.fdopen(fd, "wb") as f:
    f.write(data)
    f.flush()
    os.fsync(f.fileno())
  return data


def rom_write(image, config):
  # the ROM bootloader implements only the BOT protocol, and requires a port reset before bulk transfers
  path, _, _ = find_chestnut()
  if path is None:
    raise RuntimeError("chestnut disappeared before recovery")
  unbind_drivers(path)
  fd = open_device(path)
  try:
    fcntl.ioctl(fd, USBDEVFS_RESET)
  finally:
    os.close(fd)
  time.sleep(3)
  path, _, _ = find_chestnut()
  if path is None:
    raise RuntimeError("chestnut did not re-enumerate after reset")
  fd = claim_interface(path, setup=True)
  for ep in (0x02, 0x81):
    fcntl.ioctl(fd, USBDEVFS_CLEAR_HALT, struct.pack("I", ep))
  tag = 0

  def bulk(ep, payload, timeout):
    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)))

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Check lsusb / /sys/bus/usb/devices for 174c:2464 - if absent, reseat cable and enclosure, wait for re-enumeration, re-run the tool
  2. Use a direct, well-seated connection; avoid hubs and marginal cables for recovery flashing
  3. Check VBUS regulation (/sys/kernel/debug/regulator/smb2-vbus/enable on the intended platform) if the enclosure is bus-powered
  4. Retry the tool end-to-end - ROM recovery is idempotent and rewrites the whole image
Defensive patterns

Strategy: validation

Validate before calling

from flash import find_chestnut

if find_chestnut()[0] is None:
    raise SystemExit('device absent - reseat before starting ROM recovery')

Try / catch

try:
    rom_write(image, config)
except RuntimeError as e:
    if 'disappeared' in str(e):
        reseat_device(); rom_write(image, config)  # idempotent, safe to restart

Prevention

When it happens

Trigger: rom_write() called right after RomFallback was detected, but between detection and this scan the device disconnected: cable moved, enclosure lost power, VBUS dropped, or the device hard-crashed out of the bootloader.

Common situations: Loose USB-C connection jostled during recovery prep; power negotiation hiccup on the port; a hub dropping the device; enclosure powered from a marginal source; the ROM bootloader resetting itself once more after enumerating.

Related errors


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