0X00002736

Fix WSAENOTSOCK (0X00002736) – Not a Socket Error on Windows

This error means something tried to use a file descriptor that isn't a valid socket. Usually it's a stale socket handle or a race condition in your app.

I know this error is infuriating — you're staring at 0X00002736, and your network code just broke. I've debugged this exact thing on Windows 10 and Server 2019, and it's almost always a stale or double-freed socket handle. Let's fix it.

The Real Fix: Check Your Socket Handle Lifecycle

The error means your program passed a file descriptor that isn't a valid socket to a Winsock function like send(), recv(), select(), or closesocket(). The most common cause? You called closesocket() on a socket, then tried to use it again. Here's how to spot and fix that.

  1. Search for closesocket() calls — make sure you aren't closing the same socket twice. After you close, set the socket descriptor to INVALID_SOCKET (which is usually -1 on Windows).
    SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
    // ... use s ...
    closesocket(s);
    s = INVALID_SOCKET;  // critical: marks it as invalid
  2. Check if you're using the wrong variable — sometimes you have two variables, one is a file descriptor from _open_osfhandle() and the other is a real socket. Mixing them up causes this error. Use WSAEnumNetworkEvents() to validate the socket first if you're unsure.
  3. Look for race conditions — if you close a socket in one thread and another thread tries to send on it, you'll get 0X00002736. Add a mutex or atomic flag around the socket handle. I've seen this on multi-threaded HTTP servers where a timeout handler closes the socket while the main loop is still trying to write.

If you're using select(), verify that the socket is still valid before the call, not after. A common pattern is to call select(), then check if the socket is in the set — but if another thread closed it between those two operations, you're toast. Use WSAIsBlocking() (deprecated) or better, a proper synchronization object.

Why This Works

Winsock uses an internal table of socket descriptors. When you call closesocket(), it removes the descriptor from that table and marks the handle as invalid. If you later try to use that same integer value, Winsock sees it doesn't correspond to any active socket and returns WSAENOTSOCK (error code 10038, which is 0X00002736 in hex). By setting the variable to INVALID_SOCKET, you ensure any subsequent code that checks for validity (like if (s == INVALID_SOCKET)) catches the problem instead of passing a garbage value.

Less Common Variations

Sometimes the error isn't from your code — it's from a third-party library or the OS itself. Here are two scenarios I've run into:

1. Interop with Legacy Winsock 1.1

If you're mixing socket() calls from Winsock 2 (ws2_32.dll) with functions from Winsock 1.1 (wsock32.dll), the socket handles might not be compatible. The fix is to only use ws2_32.dll on modern Windows (XP SP2 and later).

2. closesocket() with SIO_KEEPALIVE_VALS

I once saw this error when a socket's keepalive struct pointed to freed memory. The kernel tried to read the keepalive data after the socket was closed and handed back an invalid handle. If you set SO_KEEPALIVE with custom intervals, make sure the struct tcp_keepalive is allocated in persistent memory (heap, not stack).

3. Handle Leak from DuplicateHandle()

If you're passing sockets between processes via DuplicateHandle(), the child process might not have initialized Winsock with WSAStartup(). Call WSAStartup() in every process that touches a socket. Missing that gives you WSAENOTSOCK.

Prevention: Build a Socket Lifecycle Class

The best way to never see this error again is to wrap every socket in a RAII-like class (or a simple struct in C). Here's a minimal C++ example:

class SafeSocket {
    SOCKET s;
public:
    SafeSocket() : s(INVALID_SOCKET) {}
    ~SafeSocket() { close(); }
    void close() {
        if (s != INVALID_SOCKET) {
            closesocket(s);
            s = INVALID_SOCKET;
        }
    }
    void assign(SOCKET new_s) {
        close();
        s = new_s;
    }
    bool is_valid() const { return s != INVALID_SOCKET; }
    // ... send, recv check validity first
};

Also, always call WSACleanup() only once per WSAStartup(). Calling it twice deallocates the Winsock DLL, and subsequent socket calls will fail with WSAENOTSOCK or WSANOTINITIALISED (10093).

If you're debugging an existing app, run it under Application Verifier (appverif.exe) with the “Locks” and “Handles” tests enabled — it catches double closes and use-after-close instantly.

One last thing: on Windows 7 and earlier, a bug in the AFD.sys driver could cause this error under heavy load on non-blocking sockets. Update to at least Windows 8.1 or apply KB 2919355. But 95% of the time, it's your code. Set that socket to INVALID_SOCKET and sleep better.

Related Errors in Network & Connectivity
0X00000427 Fix 0X00000427: Service Can't Connect to Service Controller 0XC00D0FCA Fix NS_E_DEVICE_NOT_READY (0XC00D0FCA) on Windows Media Player 0XC0000222 Fix STATUS_LOST_WRITEBEHIND_DATA (0XC0000222) Delayed Write Failed Error Fix DHCP Not Enabled for WiFi on Windows

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.