What's actually happening when you see 0XC0020017
The error RPC_NT_SERVER_UNAVAILABLE (0XC0020017) means your machine tried to make a remote procedure call, the call reached the endpoint mapper or the target host, and then nothing answered. The RPC runtime returns this error when the server side isn't listening, the service isn't running, or a firewall dropped the packet before it got there. It's not a credential problem — you'd get RPC_S_SEC_PKG_ERROR or an access denied instead. It's a reachability problem.
You'll see this most often when a domain-joined workstation tries to contact a domain controller after a VPN reconnect, or when a backup tool like Veeam or Windows Server Backup kicks off at 2 AM and the target host has gone to sleep. It also pops up constantly on Hyper-V hosts when the vmicvss provider can't reach the guest's RPC endpoint.
Three causes cover about 95% of cases. Work through them in order.
Cause 1: The RPC service (RpcSs) or RPC Endpoint Mapper is stopped
This is the number one cause by a wide margin. If the Remote Procedure Call (RPC) service isn't running on the target machine, every RPC call into it returns 0XC0020017 immediately. The same error appears if the RPC Endpoint Mapper (RpcEptMapper) is stopped, because the client can't resolve the dynamic port for the target service.
Both services are set to Automatic by default and are protected — you can't stop them through Services.msc without jumping through hoops. But they can fail to start after a bad patch Tuesday, after a registry cleaner nuked their Start values, or after someone ran sc config RpcSs start=disabled while "hardening" a server.
Check them from an elevated prompt:
sc query RpcSs
sc query RpcEptMapper
You want STATE : 4 RUNNING on both. If they're stopped, try to start them:
net start RpcSs
net start RpcEptMapper
If they refuse to start, check the Start value in the registry. The reason this step matters is that a Start value of 4 (Disabled) overrides every UI attempt to start the service:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\RpcSs
Start = 2 (REG_DWORD)
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\RpcEptMapper
Start = 2 (REG_DWORD)
Reboot after fixing the values. Don't try to start them in place — RpcSs is a critical service and half-started states cause weird follow-on errors.
Cause 2: Firewall is blocking RPC — especially the dynamic port range
RPC doesn't run on one port. The Endpoint Mapper listens on TCP 135, tells the client which dynamic port the actual service is on, and then the client connects to that port. Most people open 135, pat themselves on the back, and then wonder why the call still fails. What's actually happening here is that the dynamic port range (default 49152–65535 on Server 2008 R2 and later) is blocked.
Two fixes work. The clean one is to restrict RPC to a known port range and open that range on the firewall. On the target server:
netsh int ipv4 set dynamicport tcp start=5000 num=1000
netsh int ipv4 set dynamicport udp start=5000 num=1000
Reboot. Then open TCP/UDP 5000–5999 plus TCP 135 on every firewall between client and server, including Windows Firewall on both ends:
New-NetFirewallRule -DisplayName "RPC Dynamic Ports" -Direction Inbound `
-Protocol TCP -LocalPort 5000-5999 -Action Allow
If you're using the old netsh firewall on Server 2008 or 2008 R2, use netsh advfirewall instead — the old syntax gets silently ignored on newer builds.
The other fix, and honestly the one I'd pick for a small environment, is to enable the built-in firewall group Remote Service Management and Windows Management Instrumentation (WMI-In) on the target. Those rules handle the port negotiation for you.
Quick sanity check: from the client, run portqry -n target -e 135. If that's LISTENING but a subsequent portqry -n target -e 5000 (or whichever port the endpoint mapper returned) is FILTERED, you've found the block.
Cause 3: Name resolution or the endpoint mapper is returning a stale address
This one trips people up because the RPC service is running fine and the firewall is wide open. The client resolves the target hostname to the wrong IP — usually an old DHCP lease cached in DNS, or a stale entry from a decommissioned server that still holds the same hostname.
The classic scenario: you promoted a new domain controller, demoted the old one, forgot to scavenge its A record, and now every \OLD-DC RPC call resolves to an IP that no longer has RPC listening. The error is exactly 0XC0020017, not "host not found," because the IP is reachable — it's just the wrong machine.
Check what the client is actually talking to:
nslookup target-hostname
ping -a <returned-ip>
If the reverse lookup returns a different name than the forward lookup, you've got a stale record. On the DNS server:
dnscmd /RecordDelete zone target-hostname A /f
ipconfig /flushdns (run on the client)
Then re-register the correct record on the live host with ipconfig /registerdns.
If DNS is clean, check the endpoint mapper itself. From the client:
rpcdump /s target-hostname
If rpcdump returns nothing but the host is pingable, the endpoint mapper on the target has lost its bindings. The fix is a reboot of the target — RpcEptMapper doesn't cleanly reinitialize without one. There's no net stop that will do it.
Quick reference
| Symptom | Likely cause | First thing to try |
|---|---|---|
| RPC fails from every client to one host | RpcSs or RpcEptMapper stopped | sc query RpcSs then check registry Start value |
| RPC fails from one subnet but works from another | Firewall blocking dynamic port range | Fix the port range, then open it on every firewall in path |
| Intermittent RPC failures to a specific hostname | Stale DNS A record | nslookup both directions, delete stale record |
Ping works, rpcdump returns nothing | Endpoint mapper lost bindings | Reboot the target |
| Fails only after VPN reconnect | Stale route or DNS from split-tunnel | ipconfig /flushdns, check VPN adapter metric |
If none of those clear it, pull a network trace with Wireshark filtered on tcp.port == 135 and follow the conversation. The endpoint mapper's response (or lack of one) tells you exactly where the call dies.