commaai/openpilot · error · RuntimeError

chestnut did not enumerate within {timeout:g}s

Error message

chestnut did not enumerate within {timeout:g}s

What it means

Raised by Flash.connect() when, within the timeout window (default 5.0s, polled every 0.1s), find_chestnut() never returns a usable device path. The script scanned /sys/bus/usb/devices/* for the known VID:PID pairs (3801:0001/add1:0001 runtime, 174c:2464/2463 ROM) and found nothing - the chestnut bridge is not enumerated on USB.

Source

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

    self.fd = -1

  def close(self):
    if self.fd >= 0:
      os.close(self.fd)
      self.fd = -1

  def connect(self, timeout=5.0):
    self.close()
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:
      path, vid_pid, product = find_chestnut()
      if in_rom_bootloader(vid_pid, product):
        raise RomFallback("chestnut fell back to the ROM bootloader")
      if path is not None:
        self.fd = claim_interface(path)
        return
      time.sleep(0.1)
    raise RuntimeError(f"chestnut did not enumerate within {timeout:g}s")

  def reg_write(self, addr, value):
    fcntl.ioctl(self.fd, USBDEVFS_CONTROL,
                Ctrl(0x40, 0xE5, addr & 0xFFFF, value & 0xFFFF, 0, 2000, None))

  def reg_read(self, addr, length=1):
    buf = (ctypes.c_ubyte * length)()
    fcntl.ioctl(self.fd, USBDEVFS_CONTROL,
                Ctrl(0xC0, 0xE4, addr & 0xFFFF, 0, length, 2000, ctypes.cast(buf, ctypes.c_void_p)))
    return bytes(buf)

  def write_buffer(self, data):
    for i, value in enumerate(data):
      self.reg_write(0x7000 + i, value)

  def wait_controller(self, timeout=2.0):
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Check /sys/bus/usb/devices and lsusb for any 3801:0001, add1:0001 or 174c:2464 entry; if absent, reseat the USB-C cable and enclosure and retry
  2. Pass a longer timeout: flash.connect(timeout=15.0) for slow-enumerating or just-reset devices
  3. If a USBDEVFS_RESET was just issued, wait for re-enumeration before connecting (the ROM path sleeps 3 seconds)
  4. Try a different port/cable, ideally a direct connection to the host controller, no hubs

Example fix

# before
flash.connect()  # 5s default too short after reset

# after
flash.connect(timeout=15.0)
Defensive patterns

Strategy: retry

Validate before calling

from flash import find_chestnut

if find_chestnut()[0] is None:
    raise SystemExit('chestnut not on USB bus - check cable/power before continuing')

Try / catch

try:
    flash.connect(timeout=15.0)
except RuntimeError as e:
    if 'did not enumerate' in str(e):
        reseat_and_retry()
    raise

Prevention

When it happens

Trigger: Flash.connect(timeout) called when the enclosure is unplugged or powered off (no VBUS), the USB-C cable/port is bad, the device is enumerating slowly after a port reset/replug and the 5s deadline expires, or the device is in a VID:PID not in the table.

Common situations: Cable or dock that does not carry data; wrong USB port on the host; device still booting after power-on; a hub hiding the device; device that hard-hung and needs a physical replug; racing connect() immediately after a port reset (rom_write sleeps 3s for exactly this reason).

Understand the failure class

Related errors


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