Troubleshooting 11-minute read

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

If the client fails to start because a port is in use, use netstat or lsof to find the process, then change mixed-port and the external controller port and update your system proxy settings.

Check the listening address and port in the logs first

A Clash port-in-use error usually means the core cannot listen on the specified address. Common causes include running two proxy clients at once, an old core that did not exit cleanly, or a background service using the same port. Updating subscriptions, switching nodes, or changing routing rules will not resolve a local listener conflict.

Open the client's Logs page and find the full entry containing bind, listen, or address already in use. Windows may also show Only one usage of each socket address. The examples below illustrate how to identify the error type; they are not output captured from your machine:

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

The first line concerns the local proxy listener; the second concerns the controller interface. Troubleshoot the port named in the actual error—don't assume every Clash startup failure involves port 7890. If the log says permission denied or reports that access to the socket is forbidden, also consider permissions, the system's excluded port ranges, or security policies. Don't assume another process is occupying the port.

SettingPurpose and exampleWhat changes when you update it
mixed-portShared HTTP and SOCKS entry point, such as 7890Update system proxy settings and apps configured to use a proxy manually
port / socks-portSeparate HTTP and SOCKS entry points; use the values in your configurationUpdate apps that use the corresponding protocol
external-controllerController interface, for example 127.0.0.1:9090You may also need to update the dashboard or client connection settings

Windows: Find the PID with netstat, then check the executable path

Find the listening process in PowerShell

Right-click Start → Terminal, then run the following command in a PowerShell tab. You generally don't need administrator privileges to query ports; if process details aren't visible, reopen Terminal as an administrator.

netstat -ano -p tcp | findstr ":7890"

Check whether the Local Address column ends in :7890 and the state is LISTENING. A remote address that happens to contain 7890, or a connection in TIME_WAIT state, does not by itself prove that a process is listening on local port 7890. The number at the far right of each line is the PID.

To list only listeners on the target port, run this PowerShell command:

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

Suppose the PID is 1234. Check the process name and path next. 1234 is only an example—replace it with the PID you found:

tasklist /FI "PID eq 1234"
Get-Process -Id 1234 | Select-Object Id, ProcessName, Path

Verify what the process is before closing it

  1. If it's another proxy client, choose Exit from that client's system tray menu. Don't just close its main window.
  2. If it's an old core belonging to the current client, exit the client normally, then check the PID again to see whether the background process is still running.
  3. If it's another application you need, leave it running and switch the proxy to a free port.
  4. If the PID belongs to a service or system process, check Task Manager → Details and Services first. Don't force-terminate it.

A process named mihomo or clash isn't necessarily a leftover. Clients running in service mode may keep the core active in the background. If you only kill the process without stopping the tray app or service, it may start up again immediately.

macOS and Linux: Find listeners with lsof and ss

macOS: Distinguish the main window from the menu bar app

Open Applications → Utilities → Terminal and find the process listening on TCP port 7890:

lsof -nP -iTCP:7890 -sTCP:LISTEN

-nP keeps addresses and ports numeric, making the output easier to read. COMMAND, PID, and NAME identify the process, its ID, and the listening address. If a regular query returns no results but the error persists, use sudo lsof -nP -iTCP:7890 -sTCP:LISTEN to check for processes owned by other users.

Once you've identified the process, quit the corresponding client from its menu bar icon. On macOS, closing a window usually doesn't quit the app. To check the command used to start a specific PID, run:

ps -p 1234 -o pid=,ppid=,command=

Linux: Check both desktop clients and services

Most Linux distributions support ss for checking listeners. You may need elevated privileges to see full process details:

sudo ss -ltnp 'sport = :7890'

If the core belongs to a systemd service, closing the desktop window won't stop that service. Confirm which program it belongs to by checking the process path, then stop the duplicate instance through the relevant service manager. Service names depend on how the software was installed, so don't assume a service name you found online matches your machine.

  • 127.0.0.1:7890 means the listener is bound to the IPv4 loopback interface.
  • 0.0.0.0:7890 means the listener is bound to all IPv4 interfaces and may conflict with an instance bound only to the loopback address.
  • [::]:7890 is the IPv6 wildcard address. Whether it also accepts IPv4 connections depends on the system and socket settings.

So don't limit your search to lines that exactly match 127.0.0.1:7890. Check wildcard addresses, IPv6 listeners, and services running under other users too.

Change mixed-port: use the configuration that actually takes effect

Once you've identified what's using the port, you have two options: exit the unnecessary duplicate instance and keep using 7890, or leave the existing program running and move the current client to a free port. Check that 17890 is available using the commands above before changing the setting. The configuration below is for Clash cores and Clash Meta (mihomo) builds that support these fields; it is not a complete subscription file.

Change the port in the client settings first

  1. Note the current mixed port, HTTP port, SOCKS port, and controller address, and save a copy of the current configuration.
  2. Open Settings in the client and look for Port or Mixed Port. Some clients put this under Clash Settings or Core Settings; menu names vary by client.
  3. Set the mixed port to 17890, save, then use the client's option to restart the core.
  4. Open the logs again to confirm the new listener started, then use a system command to verify that the process listening on 17890 is the expected core.

If the client manages these values through YAML, update the local configuration or override file it actually uses:

# Merge this into the existing configuration; do not use this snippet to replace the full configuration.
mixed-port: 17890
allow-lan: false

allow-lan: false restricts LAN access; it does not resolve port conflicts. If you only use the proxy on this machine, don't change the listen address to 0.0.0.0 or enable LAN access just to troubleshoot.

Check for old listeners and configuration overrides

The configuration may define port, socks-port, and mixed-port at the same time. Changing the mixed port doesn't remove the other two listeners; if the error comes from a different listener, you'll need to address it separately. Don't add multiple mixed-port keys to the same YAML mapping.

Client-wide settings, merged configurations, or override rules may also take precedence over subscription files. Direct edits to a downloaded subscription may be overwritten the next time it updates. Use the client's supported persistent settings, and verify the final value in the startup logs and system listener output—not just in the editor.

Port 9090 conflict: Change the external controller port separately

If the logs specifically point to port 9090, check which process is using 9090 instead of repeatedly changing the mixed port. The controller interface lets a client or dashboard manage the core; it's not an HTTP proxy endpoint for web browsers.

# Merge this only if the client allows a custom controller interface.
external-controller: 127.0.0.1:19090

Some desktop clients manage the controller address and authentication automatically. Change these values through the client's settings whenever possible; editing generated configuration directly may prevent the main window from connecting to the core. If you connect an external dashboard manually, update its controller address to 127.0.0.1:19090 and make sure the authentication secret matches.

Update system proxy settings, terminal variables, and app-level proxies

The most common follow-up issue is apps still using the old port after the new one starts listening. The logs may no longer show a bind failure, but browsers can report a proxy connection error and the terminal may show connection refused. Check every app and setting that uses the proxy.

System proxy: Make sure it points to 17890

  • Windows 11: Go to Settings → Network & internet → Proxy → Manual proxy setup → Edit and check the address and port. If the client manages the system proxy, try turning its System Proxy option off and back on to refresh the settings.
  • macOS: Go to System Settings → Network → your current network service → Details → Proxies. Check which of Web Proxy, Secure Web Proxy, and SOCKS Proxy are enabled.
  • App-level proxy: Browser extensions, developer tools, and download managers may have their own proxy settings. Change any manually configured 127.0.0.1:7890 to 127.0.0.1:17890.

With a Proxy Auto-Config (PAC) script, the script may supply the proxy target instead of the manual proxy settings. Check which proxy source is active, and avoid enabling both an extension and a manual system proxy while updating only one of them.

Terminal: Environment variables don't update when the client changes

In PowerShell, use the following commands to temporarily update the HTTP and HTTPS proxies for the current window. The HTTPS variable still uses http:// because it points to a local HTTP proxy, which forwards HTTPS requests through CONNECT.

$env:HTTP_PROXY = "http://127.0.0.1:17890"
$env:HTTPS_PROXY = "http://127.0.0.1:17890"

On macOS or Linux, run this in your current sh, bash, or zsh terminal:

export http_proxy=http://127.0.0.1:17890
export https_proxy=http://127.0.0.1:17890

Also check uppercase proxy variables and ALL_PROXY and all_proxy; different tools don't all use the same precedence. If the settings are in a shell startup file, system environment variables, or an app's own configuration, update those persistent settings too. Temporary commands affect only the current process and its child processes; they won't change other terminals that are already open.

TUN mode uses a different traffic interception path. Enabling TUN won't free port 7890 or make a mixed port listen if binding failed. When troubleshooting a local port, don't treat toggling TUN as a fix.

Verify the fix: listener, proxy request, and settings after restart

Verify the fix in three steps so a node that's unreachable isn't mistaken for a port conflict. These are diagnostic commands; no particular response status or duration is assumed.

  1. Check the listener. Replace 7890 with 17890 in the query command above, then confirm the PID and process path belong to the current client.
  2. Specify the proxy explicitly. Bypass automatic system proxy settings and test the new local port directly.
  3. Verify after restarting. Exit the client normally and reopen it. Make sure the port setting wasn't reverted by a subscription or override, then test your browser and commonly used terminal tools.

On Windows, use curl.exe to avoid argument differences caused by the curl alias in some PowerShell environments:

curl.exe --noproxy "" --proxy http://127.0.0.1:17890 --connect-timeout 5 --max-time 20 -I https://clash15.com/

On macOS and Linux, use:

curl --noproxy "" --proxy http://127.0.0.1:17890 --connect-timeout 5 --max-time 20 -I https://clash15.com/

--noproxy "" prevents an existing bypass list from sending this test directly. A response from the destination site confirms the request path for this test, but doesn't prove that every node and rule is working. If the local connection is still refused, check the listener again. If the request reaches the core and then times out during DNS resolution or connecting to the remote server, troubleshoot the relevant DNS, routing rules, or node instead.

No listener found, but the port still won't bind

Run the query again while the error is occurring to rule out a background instance restarting briefly. If Windows reports an access-related error, check the system's excluded TCP port ranges:

netsh interface ipv4 show excludedportrange protocol=tcp
netsh interface ipv6 show excludedportrange protocol=tcp

If the target port falls within an excluded range, use a free port outside that range rather than deleting the system reservation. Virtualization and network components may depend on these ranges. The fix is complete when all four conditions are met: only the expected instance listens on the target port, the startup log no longer reports a bind failure, apps use the new port, and the setting persists after restarting the client.

For help checking system proxy settings and choosing a mode, see the system proxy setup guide. If the request reaches the core but then times out remotely, see troubleshooting connection timeouts. Resolve local port conflicts before checking subscriptions or network routes.

Clash Installer