commaai/openpilot · error · SerialException

read failed: {e}

Error message

read failed: {e}

What it means

In read(), any OSError from os.read() other than EAGAIN/EWOULDBLOCK is re-raised as SerialException 'read failed: {e}'. Common errnos: EIO (device disconnected, often on USB unplug), EBADF (fd closed concurrently), EOVERFLOW.

Source

Thrown at openpilot/common/serial.py:123

    if size <= 0:
      return b""

    buf = bytearray()
    deadline = self._deadline()
    while len(buf) < size:
      remaining = None if deadline is None else max(0.0, deadline - time.monotonic())
      if not self._wait_readable(remaining):
        break
      try:
        chunk = os.read(self._fd, size - len(buf))
      except InterruptedError:
        continue
      except OSError as e:
        if e.errno in (errno.EAGAIN, errno.EWOULDBLOCK):
          if self._timeout == 0:
            break
          continue
        raise SerialException(e.errno, f"read failed: {e}") from e
      if not chunk:
        break
      buf.extend(chunk)
    return bytes(buf)

  def readline(self) -> bytes:
    self._ensure_open()
    buf = bytearray()
    deadline = self._deadline()
    while True:
      remaining = None if deadline is None else max(0.0, deadline - time.monotonic())
      if deadline is not None and remaining == 0.0 and not buf:
        # match pyserial: timed-out readline returns empty
        if not self._wait_readable(0.0):
          return b""
      elif not self._wait_readable(remaining):
        return bytes(buf)

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Catch SerialException around reads and treat it as a disconnect: reopen the port and resync the protocol
  2. Physically reseat / replace the USB adapter or cable if EIO recurs
  3. Ensure only one thread closes the port, coordinated with readers

Example fix

// before
data = ser.read(256)

// after
try:
    data = ser.read(256)
except SerialException:
    ser.close()
    time.sleep(1)
    ser.open()  # reconnect on unplug
Defensive patterns

Strategy: try-catch

Try / catch

try:
    data = ser.read(256)
except SerialException:
    ser.close()
    time.sleep(1.0)
    ser.open()  # USB replug / device reset recovery

Prevention

When it happens

Trigger: Calling read()/readline() when the USB serial adapter is unplugged mid-read (EIO), the port is closed by another thread (EBADF), or the driver reports a hard error.

Common situations: USB cable/adapter disconnect during operation; device firmware crash resetting the CDC-ACM/FTDI device; closing the Serial from another thread while a blocking read is in flight.

Related errors


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