Fix Clash "Port in Use" on Windows: netstat, PID, and mixed-port
What This Guide Covers
You updated Clash, switched to a new GUI, or rebooted—and now the client exits immediately or shows a red status while the log screams that port 7890, 7891, or your configured mixed-port is already in use. That message is almost never a subscription problem. It means another process on Windows grabbed the same TCP (and sometimes UDP) endpoint first, or a previous Clash instance never released it. Your job is to turn a vague “cannot start” into a concrete process ID (PID), then choose: free the port or move Clash to a different port.
This article stays on the reproducible track: Command Prompt, PowerShell, netstat, optional Resource Monitor, and editing mixed-port (plus related keys) in your profile. We do not treat Windows Firewall as the main villain—firewall prompts are real, but they rarely mimic a clean “address already in use” bind failure. If you still need client setup context after you clear the port, see our Clash Verge Rev on Windows and macOS walkthrough and subscription import guide; for tooling that also binds local ports, Docker Desktop with Clash explains how another stack can sit beside the same numeric habits.
Symptoms You Should Expect
Clash-family cores listen on one or more local ports so browsers, system proxy settings, or TUN adapters can forward traffic. When the core cannot bind, you may see:
A tray application that spins and never turns “running.” A log line in the GUI or a logs file mentioning bind, listen, Only one usage, or address already in use. An upgrade that worked yesterday but fails today because a background service adopted the same default. A second copy of the same client launched by autostart while an invisible headless core is still alive.
Write down the exact port number from the message. If the UI only says “start failed,” open the detailed log; Mihomo and Clash Meta forks usually print the failing listener. Guessing “probably 7890” wastes time when your profile moved mixed-port to something else.
Which Ports Clash Actually Uses
Modern Mihomo / Clash Meta YAML still centers on a few user-visible keys. The most common footgun is mixed-port: a single port that speaks both HTTP proxy and SOCKS5 on the same listener. Many templates set 7890. Separately, legacy configs may define port for HTTP and socks-port for SOCKS; if all three exist and overlap, you still need only one free socket per enabled listener.
Less obvious conflicts come from redir-port, tproxy-port, Linux-only pieces you might copy from the internet, or an external-controller (REST dashboard) listening on 9090. DNS listeners such as dns.listen can collide on 53 or 1053 if you experimented with fake-ip stacks. Each enabled listener must own a unique port on the interface it binds—usually all interfaces (0.0.0.0) or loopback (127.0.0.1) depending on allow-lan and your GUI defaults.
Before editing YAML, confirm which keys your GUI actually writes. Some front ends merge defaults: they might inject mixed-port even when your file omits it. That is why the log line beats memory.
Step 1 — Command Prompt and netstat
Open Command Prompt as a normal user; administrator rights are not required merely to inspect listeners. Replace 7890 with the port from your error:
netstat -ano | findstr :7890
The -a flag shows all connections and listening sockets, -n prints numeric addresses (faster to read), and -o appends the owning PID. Pipes through findstr limit noise on a busy desktop. Expect lines similar to:
TCP 0.0.0.0:7890 0.0.0.0:0 LISTENING 12345
The final column is the PID. If you see multiple rows, note whether the state is LISTENING (true conflict) or ESTABLISHED (a client connection that merely uses the port as a remote endpoint—usually harmless for diagnosis). For UDP, netstat -ano -p UDP | findstr :7890 helps when a clash involves DNS or QUIC experiments, though most beginner “port in use” reports are TCP.
Step 2 — PowerShell Alternatives
PowerShell can feel friendlier when you want structured output. On Windows 10 and 11:
Get-NetTCPConnection -LocalPort 7890 -ErrorAction SilentlyContinue | Select-Object LocalAddress,LocalPort,State,OwningProcess
OwningProcess is the PID. If nothing returns, either the port is free at that instant or a race cleared it—retry right after reproducing the Clash start failure. You can map the PID to an image name in one shot:
Get-Process -Id (Get-NetTCPConnection -LocalPort 7890).OwningProcess
Wrap that in error handling when testing unknown ports; PowerShell throws if no connection matches.
Step 3 — From PID to Application
Once you have a PID, translate it to a human label:
tasklist /FI "PID eq 12345"
Or open Task Manager → Details → sort by PID. Resource Monitor (resmon.exe) → Network → Listening Ports offers the same mapping with a sortable grid; it is optional but reassuring when three different services share similar icons.
Typical culprits: another Clash, V2Ray, sing-box, an HTTP debugger, a forgotten Python dev server, corporate VPN helpers, or an older installer’s background agent. Sometimes the owner is svchost.exe; that is not a dead end—note the service name via Task Manager’s Services tab or tasklist /svc, then decide whether you may stop that stack.
Step 4 — Choose a Fix Strategy
You have two legitimate exits. Strategy A — free the port. Quit or uninstall the conflicting program, end the task if it is safe, or disable its autostart. This keeps your muscle memory (“always 7890”) intact. Strategy B — move Clash. Edit mixed-port (and matching port / socks-port if you use them) to an unused high port such as 17890, then restart the core. Update system proxy settings, browser extensions, and IDE proxy fields to the new number.
Strategy B is preferable when the other application is mandatory—think enterprise endpoint agents—or when you run multiple proxies on one machine for lab work. Strategy A is preferable when the PID is clearly a zombie copy of your own Clash GUI and you just need a clean quit.
Always close the GUI with its proper exit path first. If the core is headless, your front end may expose “Quit” versus “Stop core.” Forcing taskkill works but can leave tun adapters or routing tables in a weird half-state; use it after gentler attempts fail, and reboot if the network stack acts odd afterward.
Step 5 — Editing mixed-port Safely
When you change YAML, keep three rules: edit while the core is stopped, preserve indentation (spaces, not tabs, in most templates), and change every consumer of the old port. A minimal illustration:
mixed-port: 17890
If your file still declares port: 7890 and socks-port: 7891, either align them with non-overlapping values or rely on mixed-port alone if your client supports unified listeners. After saving, start Clash and re-run netstat -ano | findstr :17890 to confirm LISTENING belongs to the new PID from your GUI executable.
GUI-specific note: some apps store overrides in a database or JSON beside the YAML. If edits snap back on launch, use the settings screen to set the port and let the program persist it—then re-export or inspect the file to verify.
external-controller and Dashboard Collisions
A second class of failures involves the external controller, often 127.0.0.1:9090. The symptom sounds identical—bind error—but the fix is a different port key. Search your config for external-controller and either free that port or change it, then point your dashboard URL at the new value. Keeping controller on loopback is good hygiene; exposing it to LAN without auth is not.
When the PID Is Another Clash Instance
Windows autostart sometimes launches both a service and a tray app, or an updater leaves the old core alive while the new UI starts. If tasklist shows two executables from the same vendor folder, end the older one, disable duplicate startup entries in Task Manager → Startup Apps, and reboot once to clear stale listeners. Check both your user account and the HKLM run keys if you are comfortable with advanced tooling; otherwise GUI startup toggles are enough.
WSL2, Docker, and “Ghost” Listeners
Traffic from WSL2 or Docker Desktop can confuse people because the port appears to come from a virtual switch or relay, but the owning PID still lands on the Windows side for many scenarios. If netstat shows a listener you cannot map to a friendly name, read the PID anyway—Windows still attributes it. For routing-wide WSL issues that are not port binds, our Clash and WSL2 on Windows 11 article covers a different failure mode; combine that with this port guide when both symptoms appear.
Verification Checklist
After your change, walk through this list: Clash log shows core started without bind errors. netstat lists your chosen port in LISTENING with the expected PID. System proxy or browser points at the same host and port you configured. A quick curl -x http://127.0.0.1:PORT https://example.com -I returns headers when Clash runs in rule mode that permits the test domain. If HTTPS fails but HTTP works, suspect rule order or TLS inspection elsewhere—not the port bind.
Policy. Only terminate processes you recognize and are allowed to stop. On managed PCs, ask IT before killing security agents that legitimately reserve local ports.
Closing Thoughts
Port in use errors look dramatic but they are deterministic: some PID arrived first. netstat and PowerShell turn the mystery into a name, and mixed-port edits let Clash coexist with stubborn neighbors when you cannot move them. Compared with reinstalling blindly or toggling random firewall switches, this sequence saves time and keeps your config intentional.
When you want a maintained client, clear download entry, and fewer scattered release pages, start from one place. → Download Clash for free and experience the difference.
Need mixed-port context inside a full Windows GUI setup? Continue with Clash Verge Rev on Windows and macOS. Go to the download page →