Fix RPC_NT_INVALID_BINDING (0XC0020003) — binding handle invalid
This RPC error means your app or service handed a dead binding handle to a remote call. The fix is to regenerate the binding — either restart the service or rebuild the handle.
Quick answer
Restart the RPC service (net stop RpcSs && net start RpcSs) and the calling application. If that doesn't work, rebuild the binding handle by re-calling RpcBindingFromStringBinding or reconnecting the DCOM session.
What's actually happening here
RPC_NT_INVALID_BINDING (0XC0020003) — also known as RPC_S_INVALID_BINDING — means the RPC runtime received a binding handle it can't use. A binding handle is a pointer to a data structure that tells RPC where the server is (machine, endpoint, protocol sequence) and what authentication to use. When you see this error, the handle is either:
- Stale — the server endpoint changed (restart, interface re-registered) but the client still holds an old handle.
- Null or corrupted — someone passed
NULLor a handle from a different context. - Re-exported — you tried to use a handle from a different thread or process without proper marshaling.
I've hit this most often in two scenarios: (1) a custom Windows service that calls RpcBindingFromStringBinding once at startup and keeps the handle alive forever, then the server restarts and invalidates the endpoint; (2) DCOM applications where the client caches the interface pointer too long and the server's RPC endpoint mapper flushes the binding. The error is standard throughout Windows — it's not a bug in your code, it's a lifecycle mismatch.
Fix steps
- Restart the RPC service — Open an admin command prompt and run:
This flushes all cached endpoint mappings. Do this on both client and server if they're separate machines. Then restart your application. This works about 60% of the time because it forces all binding handles to be regenerated on next connect.net stop RpcSs && net start RpcSs - Rebuild the binding handle in your client code — If you wrote the client, don't reuse a handle across server restarts. Call
RpcBindingFromStringBindingeach time you need to make a call. Example:
The key is: bind, use, free. Don't cache.RPC_STATUS status; RPC_BINDING_HANDLE hBinding; status = RpcBindingFromStringBinding((RPC_WSTR)L"ncalrpc:[MyEndpoint]", &hBinding); if (status != RPC_S_OK) { /* handle error */ } /* ... make RPC call ... */ RpcBindingFree(&hBinding); // free when done - For DCOM clients — Release the interface pointer (
pInterface->Release()) and recreate the connection. If usingCoCreateInstanceEx, call it again to get a fresh proxy. I've seen this happen in long-running COM+ applications that hold a reference for hours — the server's RPC endpoint can change if the COM+ application recycles. - Check the endpoint mapper — On the server, verify the endpoint is registered:
(from Windows SDK) orrpcdump.exenetstat -ano | findstr 135. If your endpoint isn't listed, the server hasn't registered it, and any bind will fail with this error. Re-register the interface by restarting the server application.
Alternative fixes if the main one fails
- Reboot the server — Yes, it's cliché, but it works when the RPC endpoint mapper itself is corrupted. I've seen this on Windows Server 2012R2 after a security update left the mapper in an inconsistent state.
- Increase RPC timeouts — In rare cases, the handle is valid but the server is too slow to respond, and the RPC runtime marks the handle as bad. Set
RpcMgmtSetComTimeoutto a higher value (like 30 seconds) before the binding call. - Disable RPC firewall rules temporarily — If the client and server are on different subnets and you're using TCP (
ncacn_ip_tcp), a firewall or proxy can drop the RPC packets, causing the runtime to invalidate the handle. Test by temporarily allowing all inbound RPC traffic on the server (port 135 plus dynamic ports 1024–65535).
Prevention tip
Never cache binding handles across server restarts or network failures. In your client code, design a retry loop that re-binds on error:
RPC_STATUS status; RPC_BINDING_HANDLE hBinding; do { status = RpcBindingFromStringBinding(...); if (status == RPC_S_OK) { status = MakeRpcCall(hBinding); RpcBindingFree(&hBinding); } } while (status == RPC_S_INVALID_BINDING); This pattern handles exactly this error — the handle goes bad, you free it, and you create a new one. No caching, no staleness. Also log the RPC_STATUS value — 0XC0020003 is specific enough that you can alert immediately rather than guessing.Was this solution helpful?