Article View

Scroll down to read the full article.

The Phantom 'ENOBUFS': When netlink Starves on epoll (CentOS 7 Node.js Nightmare)

calendar_month July 14, 2026 |
Quick Summary: Node.js on CentOS 7 struggling with netlink socket ENOBUFS under epoll load? This isn't your ulimit problem. Fix obscure kernel buffer exhaustion now.

Listen up. You think you've seen every networking nightmare? Think again. We hit a wall with a high-performance Node.js service on CentOS 7. An obscure ENOBUFS error, specifically related to netlink sockets. Not your usual TCP/UDP stuff. Hours bled into days. Metrics looked fine. ulimit was through the roof. Still, a critical component, monitoring network interfaces for our custom traffic shaper, choked and died under moderate load.

A complex
Visual representation

The logs were a mess. Error: ENOBUFS, No buffer space available – that's the money shot. Sometimes a misleading Error: EMFILE, too many open files would pop up, but lsof showed plenty of descriptors left. This only happened during peak network churn, when our internal netlink client was actively querying interface stats. The service would recover after a restart, but fail again within minutes if load persisted.

Before you even ask, here's the toxic brew we were dealing with:

ComponentVersion
Operating SystemCentOS Linux release 7.9.2009 (Core)
Kernel Version3.10.0-1160.71.1.el7.x86_64
Node.js Runtimev16.20.2
'netlink' Library (example)@siddharth_desai/node-netlink 0.3.0

First reaction, always: ulimit -n. Jacked it up to 65535. No change. If you've battled ECONNRESET on CentOS 7, you know ulimit is often the first suspect. Not this time. Checked memory with free -h and top. Plenty available. No swap activity. General TCP/UDP sockets were fine. Only netlink cried for help.

This pushed us deep. strace on the Node.js process showed sendmsg or recvmsg calls failing with ENOBUFS specifically on NETLINK sockets. dmesg wasn't always helpful, but occasionally showed kernel: netlink: OOM in message processing or similar. It wasn't Node.js. It was the kernel itself, struggling with netlink's internal buffer management.

The Root Cause

The core problem lies in how older Linux kernels (specifically 3.x, common in CentOS 7) manage netlink socket buffers, especially when coupled with epoll under heavy, bursty event loads. epoll is great at telling you when a socket is ready, but it doesn't magically create more kernel buffer space for the data flowing through those sockets. netlink sockets are distinct; they are used for inter-process communication between user-space and kernel modules, and their buffers are often distinct from general TCP/UDP buffers.

In our scenario, the Node.js service was rapidly requesting network interface statistics via netlink. Each request and response consumes kernel buffer memory. The default sysctl values on CentOS 7 are notoriously conservative for modern, high-throughput applications. When the kernel couldn't allocate internal buffers for netlink messages (either sending or receiving), it threw ENOBUFS. Sometimes, this cascade could even lead to temporary resource starvation resembling EMFILE as the kernel struggled to keep up with internal bookkeeping, failing to allocate even metadata.

It's not just about file descriptors; it's about the finite, specialized kernel memory pools and message queues dedicated to netlink communication, which get overwhelmed before general system resources are exhausted. We needed to explicitly tell the kernel to allocate more buffer space for these specific types of interactions. This is a classic example of needing to understand the underlying system limits when scaling distributed systems beyond the marketing hype.

A close-up of a complex electronic circuit board with a single
Visual representation

The fix involved bumping several sysctl parameters directly related to network buffer management, particularly those impacting netlink and overall kernel message handling. These aren't values you'd typically touch unless you hit this exact edge case.

We need to increase the maximum size of receive and send buffers for all sockets (wmem_max, rmem_max), boost the netlink message costs (less direct, more about how the kernel charges for internal resources), and critically, the netdev_max_backlog which dictates the queue for packets coming off the network card. While not directly netlink specific, increasing these general network buffers helps alleviate pressure across the entire network stack, freeing up resources for the stressed netlink subsystem.

Run these commands directly or, better, add them to /etc/sysctl.conf for persistence:


echo "net.core.wmem_max = 16777216" | sudo tee -a /etc/sysctl.conf
echo "net.core.rmem_max = 16777216" | sudo tee -a /etc/sysctl.conf
echo "net.core.netdev_max_backlog = 10000" | sudo tee -a /etc/sysctl.conf
echo "net.core.message_cost = 500" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

A quick breakdown:

  • net.core.wmem_max: Max OS send buffer size in bytes.
  • net.core.rmem_max: Max OS receive buffer size in bytes.
  • net.core.netdev_max_backlog: Max number of packets queued on the input of a network device. Critical for handling bursts.
  • net.core.message_cost: A slightly more obscure kernel parameter related to netlink's internal resource accounting. Bumping this sometimes encourages the kernel to allow more complex or frequent netlink messages.

Remember, these are aggressive values. Monitor your system after applying them.

After applying and rebooting (or sysctl -p), we saw an immediate and sustained improvement. The ENOBUFS errors vanished under heavy load. The Node.js service became rock-solid. This wasn't about Node.js code; it was about convincing an aging kernel to stretch its internal limits for a specific, high-frequency inter-process communication.

This particular issue is a prime example of why you can't just throw ulimit at every 'too many files' or 'no buffer space' error. Sometimes, the devil is truly in the obscure kernel-level details, especially when dealing with specialized socket types like netlink on older, production-hardened Linux distributions. Know your stack. All the way down to /proc/sys.

Read Next