First, identify whether the conflict involves a proxy or control port

When starting Clash or a client powered by the Clash Meta (mihomo) core, a log message such as address already in use usually means another listener is already using the address and port the core needs. Note the protocol, address, and port shown in the error before deciding which program to stop or which setting to change. Repeatedly changing subscriptions just because startup failed rarely fixes a local port conflict.

Example log output
listen tcp 127.0.0.1:7890: bind: address already in use
listen tcp 127.0.0.1:9090: bind: address already in use

These lines serve different purposes: 7890 is commonly used as a proxy entry point, while 9090 is often used for the control interface. They are common defaults, not fixed ports required by every client. Check your current settings and startup logs.

FieldPurposeTypical symptom when in conflict
mixed-portAccepts both HTTP and SOCKS proxy connections on one portApps cannot connect to the local proxy
portDedicated HTTP proxy listenerRequests using this HTTP endpoint fail
socks-portDedicated SOCKS proxy listenerRequests using this SOCKS endpoint fail
external-controllerControl API address used by a client or dashboardThe dashboard cannot connect, read status, or switch policies

Windows: Find the process using a listening port

Step 1: Check TCP listeners and their PIDs

Open PowerShell and run the command below. It checks only local listeners on ports 7890 and 9090, so ordinary connections to remote hosts on those ports are excluded. If you get access denied or incomplete process details, reopen the terminal as an administrator.

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

If the output shows 14620 as the OwningProcess for port 7890, look up the process name, executable path, and startup arguments. PID 14620 is just an example; use the PID found on your own system.

PowerShell · Process details
Get-Process -Id 14620 | Select-Object Id, ProcessName, Path
Get-CimInstance Win32_Process -Filter "ProcessId = 14620" |
  Select-Object ProcessId, ExecutablePath, CommandLine

Step 2: Check whether the core was started more than once

  • Older proxy client: Exit the old client from its system tray menu before starting the client you want to use.
  • Background service from the same client: Stop the core or service in the client first, then exit normally. Ending the child process directly may cause it to restart automatically.
  • Another development tool or service: Leave it running and choose a different, unused port for Clash.
  • Unrecognized system process: Identify which service owns it before taking action. Don’t force-quit it just to free the port.

You can also run the following command in Command Prompt. Note that findstr :7890 may match a remote address or a similar port such as 78900. Check that the port in “Local Address” is exactly 7890 and the state is LISTENING.

Windows Command Prompt
netstat -ano -p tcp | findstr :7890
tasklist /FI "PID eq 14620"

If the log specifically reports a UDP bind failure, check the process using the port with Get-NetUDPEndpoint -LocalPort 7890. TCP and UDP use separate port spaces, so the same port number alone doesn’t mean they conflict.

macOS and Linux: Check the listening address and service owner

On macOS, use lsof to check TCP listeners; on Linux, use ss to inspect sockets and their processes. These commands only read system state and won’t stop any services. If there’s no output, check whether the client already exited after failing to start.

macOS
sudo lsof -nP -iTCP:7890 -sTCP:LISTEN
sudo lsof -nP -iTCP:9090 -sTCP:LISTEN
Linux
sudo ss -ltnp 'sport = :7890'
sudo ss -ltnp 'sport = :9090'
ps -p 14620 -o pid,ppid,user,args

Pay close attention to the listening address: 127.0.0.1:7890 is the IPv4 loopback address; 0.0.0.0:7890 listens on all IPv4 interfaces and will usually prevent another program from binding to a specific IPv4 address on the same port. [::]:7890 involves IPv6; whether it also accepts IPv4 connections depends on the system and socket settings.

If the process is managed by systemd or another service manager, stop it or change its settings through that service. Running kill alone may cause the service manager to restart it immediately, making the port appear to be “in use again.” If the process on the host is forwarding a container port, check the container’s port mapping too, not just the container itself.

Change mixed-port: Check availability, then update the persistent config

If another program needs the current port, move the mixed proxy listener from 7890 to 17890. This is only an example; first use the commands above to check whether 17890 is available. No output only means no matching listener was found at the time of the check—the result after restarting is what matters.

Where to edit settings in a GUI client or YAML file

  1. In the client settings, look for “Port,” “Mixed Port,” or “Mixed Port.” If there’s a search box, search for mixed-port.
  2. If the client provides global port settings, change them there. Menus vary between clients, so don’t assume the settings path in one version applies to all of them.
  3. When running mihomo directly, edit the config file specified by the -f startup argument. When it runs as a service, also check the arguments and working directory the service actually uses.
  4. If the client generates its runtime config from a subscription, use its supported persistent override or config-merge mechanism so a subscription update doesn’t revert the port.
config.yaml · Top-level fields to update
mixed-port: 17890
allow-lan: false
external-controller: 127.0.0.1:9090

Don’t use these three fields to replace your entire subscription config. Update the corresponding fields in the existing config, preserving its proxies, proxy groups, rules, DNS, and authentication settings. mixed-port is a top-level field; don’t indent it under proxies or proxy-groups. Don’t define the same key twice in one mapping.

If the config also contains port: 7890 or socks-port: 7890, changing only the mixed port may still leave the core trying to listen on the old port. Update or disable each listener as needed, and avoid assigning multiple listeners the same conflicting address and TCP port.

Change external-controller: Update the dashboard connection address

If the error points to port 9090, you can keep the mixed port at 17890 and move the control interface to an available port such as 19090. The control interface doesn’t handle regular browser proxy traffic, so don’t change your system proxy port to 19090 as well.

config.yaml · Example: Move the control interface
mixed-port: 17890
allow-lan: false
external-controller: 127.0.0.1:19090

If your existing config sets secret, keep it and use the same secret in your external dashboard. If you use a separate dashboard, update its API address to http://127.0.0.1:19090. Some desktop clients manage the control port and secret themselves; manually editing a generated file can disconnect the UI from the core. In that case, change the settings through the client.

  • Proxy port works but the dashboard is disconnected: Check the control address, secret, and whether the client is still using the old port.
  • Dashboard shows status but browsers fail: Check the mixed port and app proxy settings. Don’t assume the proxy endpoint is working just because the dashboard can connect.
  • Need remote dashboard access? Configure the listening address, access controls, and firewall rules separately. Don’t expose the service on all interfaces just to clear a port conflict.

allow-lan: false restricts LAN access to the proxy listener; it doesn’t configure the control API’s address binding or authentication. If the control interface is only for local use, keeping it on the loopback address is the simplest way to limit access.

After changing ports: Update system proxy and app settings

Moving to a new port takes two steps: the core listens on the new port, and clients connect to it. If you do only the first, your browser may keep using the old 7890 port, leaving the core running but pages unable to load.

ClientSettings to check
Windows system proxyManual proxy address and port under Settings → Network & Internet → Proxy
macOS system proxySystem Settings → Network → Current network service → Details → Proxies
Browser proxy extensionHTTP or SOCKS address and port saved manually in the extension
Terminal and scriptsHTTP_PROXY, HTTPS_PROXY, ALL_PROXY, and command-line arguments
Standalone control dashboardControl API address, port, and secret—not the mixed proxy port

Settings paths may vary between operating system versions. If the client manages your system proxy, toggle its “System Proxy” setting off and back on so it writes the new port, then verify the actual value. Browsers, IDEs, and download tools with their own proxy settings won’t necessarily follow the system settings.

Specify the proxy explicitly in your terminal to avoid inheriting old environment variables. The example below sends a request through the new mixed port using an HTTP proxy. Use curl.exe on Windows and curl on macOS or Linux.

Test a request through the explicit proxy
curl.exe --proxy http://127.0.0.1:17890 --noproxy "" --connect-timeout 5 --max-time 15 -I https://example.com/

The 5-second value is the connection timeout, and 15 seconds is the total request timeout—not an expected speed test result. Choose a test URL that your network and current policy allow. The HTTP status doesn’t have to be 200; check the response and logs to confirm that the request went through the proxy. A TLS certificate error, remote refusal, and local connection refusal are different types of problems.

Why binding can still fail when no process appears to be using the port

A permissions error isn’t the same as an address-in-use error

On Windows, access permissions errors and, on Unix-like systems, permission denied errors shouldn’t be treated as ordinary port conflicts. Windows may reserve some port ranges for the system or virtualization components. Use the read-only command below to check; if your chosen port falls within a reserved range, pick another available port outside it.

Windows · Check excluded port ranges
netsh interface ipv4 show excludedportrange protocol=tcp
netsh interface ipv6 show excludedportrange protocol=tcp

Don’t delete a system-reserved range just to use port 7890. On Linux, listening on ports below 1024 usually requires appropriate permissions or capabilities, but 7890 and 17890 aren’t in that range. Check your security policy and service logs to identify the actual cause.

Old process restarts automatically, or the wrong config file was edited

If the process using the port keeps getting a new PID, check startup apps, background services, and automatic recovery in other clients. If the PID stays the same but logs still show the old port, check the startup arguments, config merge order, and any global port override in the client. Changing 7890 in a subscription file doesn’t necessarily change the config the core actually runs.

If the error is cannot assign requested address, check that the bind IP belongs to the current device. For example, after switching networks, an old LAN address may no longer exist. That’s different from another program using the port.

Verify the fix: Check the listener, test a request, and restart

  1. Check which process owns the listener: Recheck ports 17890 and the control port, and verify the process path belongs to the client or core you intend to use. Don’t rely on the port merely being open.
  2. Verify the request path: Send a request with an explicit proxy command, check the client’s connection log for that request, and confirm the matched rule and outbound policy.
  3. Confirm the config persists: Restart the client and update the subscription once more. Make sure the port hasn’t reverted and that the system proxy and external dashboard reconnect.

If an explicit proxy request succeeds but your regular browser still fails, check the system proxy, browser extensions, and the browser’s own settings. If the request reaches the core but fails during DNS resolution or the remote connection, investigate DNS, nodes, and rules instead of repeatedly changing local listening ports.

A reliable way to resolve a port conflict is to read the full bind error, find the process using the port by protocol and address, stop the duplicate service or move the listener, then update every client that connects to it. This preserves services you still need and avoids a second failure where the port changed but apps keep using the old address.