Check the address in the error before deciding whether to stop a process or change the port

Work in this order: identify the port that failed to bind → find the process using it → quit the duplicate instance or choose an unused port → update the system proxy. Don’t delete your subscription or reinstall the client first. A port conflict happens while binding locally and is usually unrelated to whether remote proxy nodes are available.

Clash clients use a graphical interface to manage configuration, but the process listening on a port may be the Clash or Clash Meta (mihomo) core, or a background service started by the client. Closing the window doesn’t always stop the core. A tray app, startup item, or service mode can keep it running.

Pull three details from the error log

listen tcp 127.0.0.1:7890: bind: address already in use

This is an example log, not a result from your computer. It shows that a TCP listener failed to bind to 127.0.0.1 on port 7890. On Windows, you may also see “Only one usage of each socket address is normally permitted.” Note the actual port number; use the one in your log for the commands below.

Config fieldPurposeWhat to check
mixed-portOne endpoint for both HTTP and SOCKS proxy connections7890 and 7897 are common values, not fixed standards
port / socks-portSeparate HTTP and SOCKS endpointsCheck that neither duplicates the mixed port
external-controllerCore control API9090 is a common example, not a proxy port for internet traffic
dns.listenCore DNS listener addressMay use UDP as well as TCP; don’t check TCP alone

Windows: Find the PID and executable path for a listening port

Open PowerShell and check local TCP listeners. The examples below use ports 7890 and 7897. You can usually view the listener list without elevated permissions, but reading the executable path for another user’s process may require running the terminal as an administrator.

Get-NetTCPConnection -State Listen -LocalPort 7890,7897 -ErrorAction SilentlyContinue |
  Select-Object LocalAddress,LocalPort,State,OwningProcess

Look for OwningProcess, which gives you the process PID. If the result shows PID 6420, look up its name and executable path next. 6420 is an example only; use the PID from your results, and don’t terminate a process just because its PID matches this number.

Get-Process -Id 6420 | Select-Object Id,ProcessName,Path
Get-CimInstance Win32_Process -Filter "ProcessId = 6420" |
  Select-Object ProcessId,ParentProcessId,ExecutablePath,CommandLine

You can also check from Command Prompt

netstat -ano -p tcp | findstr ":7890"
netstat -ano -p tcp | findstr ":7897"
tasklist /FI "PID eq 6420"

netstat shows both local and remote addresses. The filter only narrows down the results: confirm that the port on the local address is 7890 and that the state is LISTENING. A remote address containing 7890, or a TIME_WAIT state, doesn’t prove that a process is occupying the local listening port.

  • If the path points to another Clash client, quit it from its tray menu, then check the port again.
  • If the path points to the current client’s core, it may already be running normally—or there may be a second instance. Check the log timestamps and parent process to tell which.
  • If the path points to another app, change the Clash port first. Don’t stop an unrelated process just to free the port.
  • If the PID changes quickly, check service mode, Startup apps in Task Manager, and the Services console. A background component may be restarting automatically.

Only consider running Stop-Process -Id 6420 once you’ve confirmed it’s a leftover core that you can no longer control through its interface. Stopping the process will interrupt its active connections. If it belongs to a service, stop it through the client that owns the service first; otherwise, the service manager may start it again immediately. Don’t terminate every process whose name contains Clash.

macOS and Linux: Check listener addresses and background services

macOS: Use lsof

sudo lsof -nP -iTCP:7890 -sTCP:LISTEN
sudo lsof -nP -iTCP:7897 -sTCP:LISTEN
ps -p 6420 -o pid,ppid,command

-nP keeps addresses and ports numeric so you can compare them directly with the log. lsof shows the command name, PID, and listening address. Quit the old client from the menu bar first, then check again. If a background service started the listener, closing the main window may leave the core running; stop it in that client’s service settings.

Linux: Use ss

sudo ss -ltnp 'sport = :7890'
sudo ss -ltnp 'sport = :7897'
ps -p 6420 -o pid,ppid,args

-l shows listeners, -t selects TCP, -n displays numeric values, and -p shows associated processes. If systemd manages the process, identify the actual service unit before stopping it—don’t guess the service name. Some clients use user services, while others use system services, so check the appropriate user-level or system-level service list.

For an ordinary leftover process, try kill -TERM 6420 to request a graceful exit, then check whether the port is free. Don’t force-kill it right away; give it a chance to shut down cleanly. If the PID changes and the port remains occupied, look for what’s restarting it instead of repeatedly killing processes.

Change mixed-port: check the new port, then save it persistently

If you need to keep the process using the port, change the Clash mixed port to an unused value. For example, if you plan to use 17890, replace the port in the commands above with 17890. No listener output only means none was found at the time of the check; confirm the bind succeeds after restarting.

  1. Find the “Mixed Port” setting in your current client and note its old value. Menu names vary by client version. Don’t mistake the core control port for the mixed port.
  2. Set the mixed port to 17890, save, then reload or restart the core as prompted by the client.
  3. Check the runtime log and confirm the bind error no longer appears for that port.
  4. Check the listener list again and confirm port 17890 belongs to the current client core.

Editing YAML directly: change only the fields you need

mixed-port: 17890
allow-lan: false

This is a top-level config snippet, not a complete subscription. Merge it into your existing config and keep your current proxies, proxy groups, and rules. allow-lan: false means this example doesn’t allow LAN access. If your current config serves another purpose, preserve its settings instead of replacing the whole file.

Check port, socks-port, external-controller, and any other listener in the same config. Avoid assigning the same address and port to two separate listeners. Don’t add a second mixed-port key: how duplicate keys are handled varies by parser.

Subscription updates may overwrite the subscription file, and temporary runtime configs may be regenerated on restart. Prefer the client’s persistent port setting or its supported override mechanism. If ports are set in both places, inspect the effective config and logs to confirm the running port is 17890. The client determines how overrides are merged, so one line in an editor doesn’t tell the whole story.

For more on available fields, see Mixed Port Configuration; for YAML indentation, see YAML Configuration Basics. These local listener settings don’t require changing the server port on a proxy node.

Update the system proxy: changing the port also means updating the connection endpoint

If the core now uses 17890 but the system proxy still points to 7890, your browser will still fail to connect. If the client manages the system proxy, turn its “System Proxy” switch off and back on to refresh the address. Then verify it in system settings—don’t rely on the switch alone.

  • Windows 11: Settings → Network & internet → Proxy → Manual proxy setup → Edit. Check that the address is 127.0.0.1 and the port is 17890. In Windows 10, look for the “Use a proxy server” switch.
  • macOS 13 and later: System Settings → Network → your current network service → Details → Proxies. Check the enabled web proxy, secure web proxy, or SOCKS proxy. With a mixed port, the proxy types you need can point to the same local port.
  • Linux desktop: Check the manual proxy settings in your desktop environment. GNOME and KDE use different menus, so don’t assume every distribution has the same path.

Browser extensions, download tools, IDEs, and terminals may use their own proxy addresses rather than following the system proxy. Update any manually entered 7890 or 7897 values to 17890. After changing terminal environment variables, reopen old terminals and apps; they may still have the previous values.

# View proxy environment variables in the current shell; output varies by shell
env | grep -i proxy

# View proxy environment variables in PowerShell
Get-ChildItem Env: | Where-Object Name -Match 'proxy'

These commands only display values; they don’t change them. Check HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, and NO_PROXY. When using a regular HTTP mixed endpoint to reach an HTTPS website, HTTPS_PROXY is commonly set to http://127.0.0.1:17890. The variable name describes the request type; it doesn’t mean the local proxy must use TLS.

Verify the fix: check the listener, proxy endpoint, and a real request

After fixing the issue, test with a request that explicitly specifies the proxy address. This avoids interference from cached system proxy settings or browser extensions. The reserved example domain below is for testing only; this isn’t a speed test, and the result doesn’t mean every site is reachable.

# Windows PowerShell: call curl.exe explicitly to avoid the legacy alias
curl.exe --proxy http://127.0.0.1:17890 --connect-timeout 5 --max-time 15 -I https://example.com

# macOS / Linux
curl --proxy http://127.0.0.1:17890 --connect-timeout 5 --max-time 15 -I https://example.com

If the request can’t connect to 127.0.0.1:17890, first check whether the core is listening. If the local proxy connection succeeds but the destination times out or returns a DNS or TLS error, the local port issue may already be resolved. Next, check which rule matched, how the destination resolves, and which proxy is selected. An HTTP header or tunnel response is only a troubleshooting clue; don’t treat every status code as proof that the entire connection works.

Additional checks when no process shows up

  • If the log says the failed listener is UDP: on Windows, run Get-NetUDPEndpoint -LocalPort 7890; on Linux, run sudo ss -lunp 'sport = :7890'; on macOS, run sudo lsof -nP -iUDP:7890. Replace the port with the one in the error.
  • Windows permission error: run netsh interface ipv4 show excludedportrange protocol=tcp to check excluded port ranges. If IPv6 is involved, check its corresponding ranges too. Prefer an unused port outside those ranges; don’t delete system reservations.
  • If the port was just freed but the bind still fails, make sure the log timestamp is from the current startup, not an old entry retained in the interface. Then check for a service that restarts automatically.
  • If the port reverts after a restart, check subscription updates, override priority, and the client’s persistent settings to find what’s writing the old value back.

Keep a record you can check later

Record the old and new ports, the path of the process that had the port, and where you changed the setting. After the next reboot, confirm that only the expected client is listening on 17890 and that the system and app proxies point to the same endpoint. Before disabling the client later, turn off the system proxy first so the system doesn’t keep sending requests to a stopped local port.