Quick answer
If you get ERROR_PIPE_LOCAL (0xE5), you're trying to connect to a named pipe that's local from a remote machine. The pipe server called CreateNamedPipe with PIPE_REJECT_REMOTE_CLIENTS flag, or the pipe name didn't include a server name. Switch to using the same machine, or change the server to call CreateNamedPipe with PIPE_ACCEPT_REMOTE_CLIENTS.
What this error actually means
Here's the deal: ERROR_PIPE_LOCAL (0x000000E5) is Windows telling you "this pipe only works locally, stop trying to reach it from another computer." The error number in decimal is 229. You'll see it most often when you're writing a service or app that uses named pipes for IPC and you try to connect from a different machine on the network.
The reason this happens is that CreateNamedPipe has a parameter called dwPipeMode. In that parameter, you can set PIPE_REJECT_REMOTE_CLIENTS (value 0x08). When that flag is set, any WaitNamedPipe or CallNamedPipe from a remote machine fails with this error. The pipe literally won't accept connections from anywhere but localhost.
I see this a lot in legacy code where developers didn't think about remote access, or in security-hardened apps that intentionally block remote pipe connections.
Fix steps
- Check the pipe server code. Look at the
CreateNamedPipecall. Find thedwPipeModeargument. If it includesPIPE_REJECT_REMOTE_CLIENTS, change it toPIPE_ACCEPT_REMOTE_CLIENTS(value 0x00). The flag constant is missing in some older SDK headers, so check the actual hex value. - Verify the pipe name format from the client. When calling
WaitNamedPipeorCreateFileon the client, the pipe name must start with\\SERVERNAME\pipe\. If you use\\.\pipe\(dot for local machine), it only works locally. Clients on other machines must use the server's actual network name or IP address. - Check firewall and permissions. Even if the pipe accepts remote clients, the Windows Firewall might block the RPC or SMB traffic that named pipes rely on. Open up ports 445 and 135 for testing. Also make sure the server process runs as a user that has network logon rights.
- Test locally first. Run both client and server on the same machine using
\\.\pipe\mypipe. If that works but remote doesn't, you've narrowed it down to either thePIPE_REJECT_REMOTE_CLIENTSflag or network issues.
Alternative fixes if the main one fails
- Use TCP sockets instead. Named pipes are convenient, but if you need cross-machine communication and can't change the server code, TCP is more flexible. You lose the security context impersonation that pipes offer, but you gain simplicity.
- Run the client on the same machine. This sounds stupid but sometimes it's the quickest workaround. If you control deployment, just put the client on the server box.
- Check the server's impersonation level. If the server uses impersonation with
SECURITY_IMPERSONATIONor higher, some clients might fail. Switch toSECURITY_ANONYMOUSduring testing to rule it out.
Prevention tip
When you write named pipe code, always decide upfront whether the pipe needs to accept remote connections. If yes, explicitly pass PIPE_ACCEPT_REMOTE_CLIENTS in CreateNamedPipe. Never rely on the default (which is the accept flag, but many old examples don't mention it). Also, use GetLastError() immediately after every pipe API call and log the error code. This single practice would have saved you hours of debugging today.