commaai/openpilot · error · SerialException

write failed: {e}

Error message

write failed: {e}

What it means

Raised by Serial.write when os.write on the serial fd fails with an OSError other than EAGAIN/EWOULDBLOCK (which are handled by select+retry) or InterruptedError. Like the read path, it means the tty channel itself is failing, not just busy.

Source

Thrown at openpilot/common/serial.py:173

      if chunk == b"\n":
        return bytes(buf)

  def write(self, data: bytes) -> int:
    self._ensure_open()
    if not data:
      return 0
    view = memoryview(data)
    total = 0
    while total < len(data):
      try:
        n = os.write(self._fd, view[total:])
      except InterruptedError:
        continue
      except OSError as e:
        if e.errno in (errno.EAGAIN, errno.EWOULDBLOCK):
          select.select([], [self._fd], [], None)
          continue
        raise SerialException(e.errno, f"write failed: {e}") from e
      if n == 0:
        raise SerialException("write returned 0")
      total += n
    return total

  def flush(self) -> None:
    self._ensure_open()
    termios.tcdrain(self._fd)

  def reset_input_buffer(self) -> None:
    self._ensure_open()
    termios.tcflush(self._fd, termios.TCIFLUSH)

  def reset_output_buffer(self) -> None:
    self._ensure_open()
    termios.tcflush(self._fd, termios.TCOFLUSH)

  def _close_fd(self) -> None:

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Catch SerialException around writes and reopen the port on failure
  2. Check that the peripheral is powered and the USB enumeration is intact (dmesg)
  3. If flow control is enabled, confirm the peer drives CTS or disable CRTSCTS on the Serial config

Example fix

// before
ser.write(data)

// after
try:
  ser.write(data)
except SerialException as e:
  print(f"serial write failed: {e}, reopening")
  ser.close()
  ser = Serial(devpath, baudrate)
  ser.write(data)
Defensive patterns

Strategy: try-catch

Validate before calling

import os

def can_write(devpath: str) -> bool:
    try:
        fd = os.open(devpath, os.O_WRONLY | os.O_NONBLOCK)
    except OSError:
        return False
    os.close(fd)
    return True

Try / catch

from common.serial import SerialException
try:
    ser.write(data)
except SerialException as e:
    ser.close()
    ser = Serial(devpath, baudrate)
    ser.write(data)

Prevention

When it happens

Trigger: Calling write() after device unplug (EIO/ENODEV), writing to a closed fd (EBADF), or the tty driver rejecting the write due to hardware flow control being stuck (device not asserting CTS when CRTSCTS is enabled).

Common situations: Peripheral power-cycled or unplugged while a writer thread is streaming, full hardware FIFO with no reader on the device side, flow-control mismatch between endpoints.

Related errors


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