commaai/openpilot · error

Failed to bind CAN socket

Error message

Failed to bind CAN socket

What it means

Emitted by SocketCanStream::connect() when bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) fails after the interface index was resolved — the socket could not be attached to the selected CAN interface. addr.can_family is AF_CAN and can_ifindex comes from the prior SIOCGIFINDEX, so failure here is about interface state or privileges, not the name.

Source

Thrown at openpilot/tools/cabana/streams/socketcanstream.cc:69

  // Enable CAN-FD
  int fd_enable = 1;
  setsockopt(sock_fd, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &fd_enable, sizeof(fd_enable));

  struct ifreq ifr = {};
  strncpy(ifr.ifr_name, config.device.c_str(), IFNAMSIZ - 1);
  if (ioctl(sock_fd, SIOCGIFINDEX, &ifr) < 0) {
    fprintf(stderr, "Failed to get interface index for %s\n", config.device.c_str());
    ::close(sock_fd);
    sock_fd = -1;
    return false;
  }

  struct sockaddr_can addr = {};
  addr.can_family = AF_CAN;
  addr.can_ifindex = ifr.ifr_ifindex;
  if (bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    fprintf(stderr, "Failed to bind CAN socket\n");
    ::close(sock_fd);
    sock_fd = -1;
    return false;
  }

  // Set read timeout so the thread can check for interruption
  struct timeval tv = {.tv_sec = 0, .tv_usec = 100000};  // 100ms
  setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

  return true;
}

void SocketCanStream::streamThread() {
  struct canfd_frame frame;

  while (!exit_) {
    ssize_t nbytes = read(sock_fd, &frame, sizeof(frame));
    if (nbytes <= 0) continue;

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Bring the interface up before connecting: `sudo ip link set can0 up` (and verify state UP in `ip link show can0`).
  2. If the adapter keeps dropping to bus-off, check wiring/termination and the configured bitrate, then `ip link set can0 down && ip link set can0 up type can bitrate <rate>` to restart it.
  3. Grant CAP_NET_RAW (`setcap cap_net_raw+ep <cabana binary>`) if strerror said 'Permission denied'.
  4. Reconnect the adapter and retry — an ENODEV race resolves once the interface is back.

Example fix

# before
# stderr: Failed to bind CAN socket
ip link show can0   # 'state DOWN'

# after
sudo ip link set can0 up
cabana   # bind(sock_fd, {AF_CAN, ifindex}) succeeds, stream starts
Defensive patterns

Strategy: validation

Validate before calling

// Check the interface is UP before bind():
#include <net/if.h>
#include <sys/ioctl.h>
bool canInterfaceUp(const std::string &ifname, int sock_fd) {
  ifreq ifr = {};
  strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
  if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) != 0) return false;
  return (ifr.ifr_flags & IFF_UP) != 0;
}

Prevention

When it happens

Trigger: connect() reaching bind() when the interface is down (ENETDOWN — binding a CAN_RAW socket to a downed interface), permissions denied (EACCES without CAP_NET_RAW for this operation), or the interface vanished between the ioctl and the bind (ENODEV race after unplugging the USB-CAN adapter). The fd is closed and sock_fd reset to -1.

Common situations: Adapter present and named correctly but never brought up (`ip link set canX up` skipped); interface went down due to a CAN bus error state (bus-off) before cabana connected; unplugging the adapter at the exact moment of connect; running unprivileged without CAP_NET_RAW.

Related errors


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