Yeah, that error's annoying. You write what looks like correct code, and Windows just says "nope, that address isn't valid here." Let's fix it.
The Most Likely Fix: Your IP Address Doesn't Belong to This Machine
The number-one cause: you're trying to bind your socket to an IP address that isn't assigned to any local network interface. This happens constantly when people hardcode 192.168.1.50 from their dev machine but then run the code on a server with 10.0.0.25.
Quick test: Open a command prompt and run:
ipconfig | findstr /R "^[0-9]\."
That lists all local IPv4 addresses. If the IP you're using in your bind() call isn't in that list, that's your problem. Fix it by either:
- Using
INADDR_ANY(0.0.0.0) in your code — this binds to all local interfaces. - Or reading the correct IP from a config file or environment variable.
Here's the C++ pattern that avoids this:
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = htonl(INADDR_ANY); // binds to everything local
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
// handle error properly
int err = WSAGetLastError();
if (err == WSAEADDRNOTAVAIL) {
// now you know why
}
}
Second Cause: Port Already Claimed by Another Process
Windows is strict — if a port is in use, bind() throws this error even if the IP is valid. The error message says "address" but the real issue is the port number isn't available either. Run this to check:
netstat -ano | findstr :8080
If you see LISTENING or ESTABLISHED on that port, something else grabbed it. Kill the process with taskkill /PID <pid> /F or change your port.
One tricky scenario: You reboot and still get this error. What's happening is the previous instance of your app didn't clean up properly — Windows holds the port in TIME_WAIT state for 2–4 minutes after the socket closes. The real fix here is to set SO_REUSEADDR on your socket before binding:
int reuse = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse));
That tells Windows to let you reuse the address even if it's in a lingering state. Works on Windows 10 and Server 2019 and later.
Third Cause: IPv6 vs IPv4 Mismatch
If you're using AF_INET6 (IPv6) but passing an IPv4 address structure, Windows gets confused. This happens when you copy-paste socket code from an IPv4 example but change the family. The error will be WSAEADDRNOTAVAIL because the address format doesn't match the socket type.
The fix: Use getaddrinfo() instead of manually building sockaddr_in structures. That function handles all address families correctly:
struct addrinfo hints, *res;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // let it pick IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM;
int status = getaddrinfo("localhost", "8080", &hints, &res);
if (status != 0) {
// gai_strerror(status) tells you what went wrong
}
// Now bind using res->ai_addr, res->ai_addrlen
This is the modern way. Manual sockaddr_in construction is error-prone.
Less Common But Real: Dynamic IP Changes
Your laptop's on Wi-Fi and the DHCP lease renews. Your app was bound to 192.168.1.10 but now the machine has 192.168.1.11. Any new socket trying to bind to the old IP throws this error. The existing connections might still work (they use their original socket), but new ones fail.
Real-world trigger: You're running a game server or media streaming app on a laptop, move to another room, the access point changes, and suddenly your service won't start. Check ipconfig — your IP changed.
Prevention Going Forward
Here's what I do to never see this error again:
- Always bind to
INADDR_ANYunless you have a specific security reason to restrict to one interface. If you must restrict, read the IP from a config file, not from hardcoded constants. - Set
SO_REUSEADDRon every server socket. It costs nothing and prevents the TIME_WAIT trap. - Use
getaddrinfo()for address resolution. It's the standard way since Windows Vista and avoids family mismatches. - When you catch
WSAEADDRNOTAVAILin your error handler, log both the IP and port you tried to bind to. That debug output saves you an hour the next time it happens. - On production servers, run a scheduled task that logs all listening ports once a minute. That way you can see if something stole your port before your service started.
This error is almost always a configuration mistake, not a bug in the OS. Get the IP right, get the port right, and Windows will happily hand you that socket.