nodejs/node · error

select fail: %d

Error message

select fail: %d

What it means

Printed by the adig tool's event loop at adig.c:900 when the select() system call returns a negative value (count < 0) and the error is neither EAGAIN nor EINTR. The message includes the numeric errno value. On Windows it uses WSAGetLastError(), on other platforms errno. The tool returns 1 (failure), terminating the DNS query loop. select() monitors the file descriptors that c-ares is watching for DNS response traffic.

Source

Thrown at deps/cares/src/tools/adig.c:900

    memset(&tv, 0, sizeof(tv));

    nfds = ares_fds(channel, &read_fds, &write_fds);
    if (nfds == 0) {
      break;
    }
    tvp = ares_timeout(channel, NULL, &tv);
    if (tvp == NULL) {
      break;
    }
    count = select(nfds, &read_fds, &write_fds, NULL, tvp);
    if (count < 0) {
#ifdef USE_WINSOCK
      int err = WSAGetLastError();
#else
      int err = errno;
#endif
      if (err != EAGAIN && err != EINTR) {
        fprintf(stderr, "select fail: %d", err);
        return 1;
      }
    }
    ares_process(channel, &read_fds, &write_fds);
  }
  return 0;
}

typedef enum {
  OPT_TYPE_BOOL,
  OPT_TYPE_STRING,
  OPT_TYPE_SIZE_T,
  OPT_TYPE_U16,
  OPT_TYPE_FUNC
} opt_type_t;

/* Callback called with OPT_TYPE_FUNC when processing options.
 * \param[in] prefix  prefix character for option

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Check the numeric errno printed: EBADF (9) means an invalid FD — investigate whether c-ares sockets were prematurely closed.
  2. Increase the file descriptor limit with 'ulimit -n' if nfds exceeds the soft limit.
  3. If running in a container, verify the seccomp profile and namespace settings allow select() and socket operations.
  4. Ensure only one thread is using the c-ares channel and that ares_destroy is not called concurrently with the event loop.

Example fix

// before: event loop fails on select error
// adig example.com  // prints 'select fail: 9' (EBADF)

// after: check fd limits and channel lifecycle
ulimit -n 65536       // raise fd limit
// ensure ares_destroy(channel) is called only after event_loop returns
Defensive patterns

Strategy: validation

Validate before calling

// Before entering the event loop, check fd limits
#include <sys/resource.h>
struct rlimit rl;
if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
    if (rl.rlim_cur < 1024) {
        rl.rlim_cur = rl.rlim_max;
        setrlimit(RLIMIT_NOFILE, &rl);
    }
}
// Ensure the c-ares channel is valid and not destroyed concurrently

Try / catch

// In the event loop, handle EAGAIN/EINTR gracefully (adig already does this)
// For other errors, log errno and break rather than crash
count = select(nfds, &read_fds, &write_fds, NULL, tvp);
if (count < 0 && errno != EAGAIN && errno != EINTR) {
    // log errno, clean up channel, exit gracefully
    break;
}

Prevention

When it happens

Trigger: The select() call in adig's event_loop (line 892) fails with an unrecoverable error. This happens when the file descriptor set passed to select() contains an invalid FD (EBADF), the nfds argument exceeds the process's FD limit, or the system call is interrupted by a signal that is not EINTR/EAGAIN. On Windows, a WinSock error such as WSAENOTSOCK or WSAEINVAL triggers it.

Common situations: Running adig in a container or sandbox with restricted file descriptor limits. A c-ares channel has internal sockets that were closed out from under it (double-close, use-after-close). A misconfigured seccomp filter blocks select(). Running on a platform where select() has platform-specific quirks (very large FD numbers).

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/68b9d858d1accb71. Report an issue: GitHub.