Clash Port Already in Use: Find the Process Holding 7890 and Change It

A startup error bind: address already in use usually means port 7890 is already held by another process. This guide uses netstat and lsof to identify the offending process, then walks through changing the mixed port in both the config file and the client UI.

SEC-01

What the error actually means

Clash-family clients (including any GUI built on the mihomo core) try to bind a set of local ports on startup to receive proxy requests from the system or browser. The most common one is the mixed port 7890 (mixed-port), which accepts both HTTP and SOCKS5 connections. If that port is already claimed by another program, the core throws an error like this in the log and exits immediately:

FATA[0000] Start Mixin server error: listen tcp 127.0.0.1:7890: bind: address already in use

The key phrase is bind: address already in use — it makes clear the problem isn't your subscription or rules, but that at the operating-system level this port number is already taken, so the new process can't bind to it. Other ports that show the same symptom include 7891 (SOCKS port on some clients), 9090 (the external-controller port), and 53 (DNS listener). The diagnosis approach is identical for all of them; this article uses the most common case, 7890, as the example.

NOTE

Port conflicts and subscription/node failures are two entirely different problems. A port conflict means the client fails to start or exits immediately after launch; a subscription issue means the client runs fine but just can't reach the target site. Identifying which stage the error happens at saves a lot of time.

SEC-02

Who's most likely to be holding 7890

7890 isn't a reserved system port, so in theory any program could claim it first. In practice, the most frequent culprits are:

  • Two Clash-family clients running on the same machine. For example, having both Clash Verge Rev and Clash Plus installed, both using the default 7890 — if the first one didn't shut down cleanly, the second can't grab the port.
  • The previous process didn't exit cleanly. System sleep, force-killing the process from Task Manager, or a core crash that leaves the main app unable to clean up child processes can all leave a zombie process still holding the port.
  • Another proxy tool is using the same default port. Some older proxy tools or packet-capture/debug proxies also default to 7890 or a nearby range.
  • A Docker container or WSL2 service is port-forwarding a container's internal service onto host port 7890.

Regardless of the cause, the approach is the same: first identify who's holding the port, then decide whether to close it or give Clash a different port instead. Rebooting blindly sometimes works temporarily, but without knowing the root cause it will likely recur.

SEC-03

Finding the process on Windows with netstat

Open Command Prompt or PowerShell and run:

netstat -ano | findstr :7890

Under normal circumstances you'll see one or more lines like this:

TCP    127.0.0.1:7890    0.0.0.0:0    LISTENING    18420

The last column, 18420, is the PID of the process holding the port. Next, look up the process name from that PID:

tasklist | findstr 18420

If the output shows a leftover main process from your client (e.g. clash-verge.exe or mihomo.exe), it's indeed a stale process — end it manually via Task Manager, or run:

taskkill /PID 18420 /F

Then restart the client. If the PID belongs to an unfamiliar program, check what it does first before deciding whether to close it or change Clash's listening port instead (see below).

WARN

Don't run taskkill on a process without knowing what it is. If the PID belongs to a system service or security software, force-killing it could cause other problems — in that case, changing the port is safer than killing the process.

SEC-04

Finding the process on macOS / Linux with lsof

macOS and most Linux distributions come with lsof (List Open Files), which gives a clearer view than netstat:

lsof -i :7890

Example output:

COMMAND     PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
mihomo    22187 alice    7u  IPv4 0x1a2b      0t0  TCP 127.0.0.1:7890 (LISTEN)

The COMMAND column gives the process name directly, and PID is the process ID. Once you've confirmed it's a stale Clash core process, kill it:

kill -9 22187

If your system doesn't have lsof (some minimal Linux containers), use ss instead:

ss -tlnp | grep 7890

This also outputs a pid= field at the end, and the rest of the process is the same. On Linux, if the process is owned by a user account without sufficient privileges to kill it, prefix the command with sudo.

SEC-05

Method 1: Change the port in the client UI

If 7890 is held by a background program you'd rather not close (say, a long-running utility you actually need), it's usually easier to give Clash a different port instead of touching the other program. Most GUI clients have a port-change option in Settings, typically at this path:

  1. Open the client's settings panel

    Find "Settings" or the gear icon on the main screen, then go to the network/port section. Naming varies slightly by client, but you'll always find fields for mixed port, HTTP port, and SOCKS port grouped together.

  2. Locate the Mixed Port field

    Change 7890 to a port that isn't in use, such as 17890 or 7899. Pick something above 1024, below 10000, and uncommon enough to avoid clashing with other software.

  3. Save and restart the core

    Most clients require you to click "Restart Core" or "Apply" after changing the port — simply saving the settings page may not rebind the port right away.

  4. Sync the system proxy port too

    If "Set as system proxy" is enabled, make sure the port number in your system proxy settings is updated to match the new mixed port — otherwise the core runs fine but traffic still can't get through.

SEC-06

Method 2: Edit the port field directly in the config file

If you maintain your config manually, or the client UI isn't accessible right now, you can edit the YAML config directly. Locate these lines in your subscription config (field names may vary slightly by version):

mixed-port: 7890
allow-lan: true
external-controller: 127.0.0.1:9090

Change the value after mixed-port to a free port, for example:

mixed-port: 17890

If your client uses separate HTTP and SOCKS ports instead of a unified mixed-port, the relevant fields are typically:

port: 7890
socks-port: 7891

Edit whichever applies. Note that external-controller uses a separate port (9090 by default) — it's the management API for the panel/dashboard, not the traffic-forwarding port. If the error actually references 9090, edit that line instead of mixed-port. Save the file and restart the client, or reload the config, for the new port to take effect.

WARN

If you edit the config manually while the client is set to "auto-update subscription overwrites local config," the next subscription refresh may revert your port change back to default. For a port you want to keep long-term, also set it in the client UI so both places stay in sync.

SEC-07

Three things to double-check after changing the port

After changing the port number, anything that referenced 7890 needs to be updated too, or you'll run into a new problem — "the client starts but I can't browse the web":

  • The proxy port in your browser extension. If you manually configured a proxy address like 127.0.0.1:7890 in an extension such as SwitchyOmega, update the port number there as well.
  • System-level proxy settings. If you manually entered a port number under Windows' Settings → Network & Internet → Proxy, or macOS's System Settings → Network → Proxies, update those too.
  • TUN mode isn't affected. If you're using TUN mode instead of the system proxy, traffic goes through the virtual network adapter rather than the mixed-port, so changing the port usually doesn't disturb an existing TUN setup. It's still worth restarting the client once to confirm the core has fully reloaded.
SEC-08

Confirming the port is actually free

After killing the process or changing the port, don't just assume it's fixed — verify with a command. On Windows, run again:

netstat -ano | findstr :7890

No output means the port is currently free and safe to use. On macOS / Linux, run:

lsof -i :7890

Again, no output means the port is free. Then start the Clash client — under normal conditions the log should show a success message like this instead of the previous FATA-level error:

INFO[0000] Mixed(http+socks) proxy listening at: 127.0.0.1:7890

Seeing this line means the mixed port bound successfully and the client is now listening normally — you can move on to configuring the system proxy or browser extension.

SEC-09

If the problem persists after changing the port

In rare cases, even switching to a port that "looks free" still throws the same bind error. If that happens, check the following:

  1. Confirm you edited the config that's actually loaded

    Some clients support multiple profiles — you may have edited profile A while the client is actually loading profile B, in which case your change simply never takes effect.

  2. Check whether security software is blocking the port bind

    Some security software blocks unfamiliar programs from binding local ports. Add the Clash client to the trusted list, or temporarily disable the relevant protection, then test again.

  3. Try an entirely uncommon port number

    Some ranges are reserved by the system or other background services. Try a five-digit, non-round port number (like 27891) to rule out an issue with the range itself.

Working through these checks one by one covers the vast majority of port-conflict scenarios. The core principle never changes: use system commands to confirm who's actually holding the port first, then decide whether to close that process or give Clash a different one — there's no need to reinstall the client or re-download your subscription.

Download Client