First, tell a hidden window from a UI crash or core exit
“Clash closes as soon as it opens” can describe three different issues: the window may be minimized to the system tray, the UI process may have crashed, or the UI may still be running while the core fails to start. Config errors and port conflicts usually affect the core first and do not necessarily close the entire client. Identify which layer is failing before deciding whether to check the config or repair the runtime environment.
- Check background processes. On Windows, press
Ctrl + Shift + Escto open Task Manager. On macOS, open Activity Monitor; on Linux, runps -ef. If the window has disappeared but the client and core are still running, check the system tray, menu bar, and window positions across your displays. - Record the conditions that trigger the issue. Note whether it happens on a fresh install, after an upgrade, after importing a subscription, or after enabling TUN. Record your OS version, CPU architecture, client version, and core version—not just “the latest version.”
- Exit the client completely. Quit from the system tray menu, confirm that its processes have ended, and try again. An old background instance may still be holding a port; repeatedly double-clicking the app only adds confusion.
Find the cause in the logs: note the startup time and first error
Client logs, core logs, and system crash reports answer different questions. Client logs cover UI initialization, core paths, and service connections. Core logs cover YAML, listening ports, and rule loading. System reports help identify runtime or shared-library issues and unexpected process exits.
Find startup failure records for your OS
- Windows: Press
Win + R, entereventvwr.msc, then open Windows Logs → Application. Find entries such as “Application Error” around the time of the crash, and note the faulting application, faulting module, and exception code. Client data may be under%APPDATA%or%LOCALAPPDATA%; portable builds may store it beside the executable. Check the client documentation and startup logs to confirm the actual location. - macOS: Open Console and check the crash reports. You can also look in
~/Library/Logs/DiagnosticReports/. Note the process name, exception type, and termination reason. Make sure you are not mistaking a report from another app for the proxy client’s crash log. - Linux: Launch the installed executable from a terminal and watch standard error. If your system uses systemd, check
journalctl --user -b --since "10 minutes ago". If crash reporting is enabled, usecoredumpctl listto find the process. Not all distributions enable the same crash-reporting tools.
Use log keywords to choose your next step
| Log message | Check first | How to verify |
|---|---|---|
yaml: line、unmarshal | Indentation, field types, and merged config | Test the actual loaded file with the same core |
address already in use | Port already has a listening process | Find the PID for that port in the logs |
permission denied | Execute permission, write access to the directory, and TUN permissions | Determine whether the failure involves a file or a network device |
no such file、exec format error | Core path, missing file, and CPU architecture | Check that the file exists and matches your system architecture |
| WebView, shared libraries, or a faulting module | Graphical UI runtime | Check dependencies based on the client’s UI technology |
“Core stopped” at the end of a log is usually just the result. Look earlier in this startup session for the first specific error, and keep about 30 lines before and after it. Before sharing logs, redact subscription URLs, credentials, controller secrets, and personal directory names. Proxy server addresses may also be sensitive.
Roll back the config: validate the YAML the client actually loads
If the client starts failing right after a subscription update, suspect a config change first. The original subscription file may not be the final file read by the core: the client may merge in overrides, scripts, rule snippets, or TUN settings. Validating only the downloaded subscription will not catch errors introduced during merging.
- Exit the client completely. Back up the current subscription, override files, and client settings; do not delete the data directory.
- Restore the most recent config that started successfully, and temporarily disable any newly added overrides or scripts. If you cannot open the UI, back up your data and follow the client’s documentation to restore the relevant config file. Do not guess how its internal database is structured.
- Test the final config with the core bundled with the client. Older Clash versions and mihomo support different protocols and fields, so a successful test with a different core does not prove the config will work.
- Once the client starts again, re-enable subscription updates, rule sets, custom DNS, and TUN one at a time to find which change triggers the issue.
For example, with mihomo, open a terminal in the core’s directory, save a copy of the config to check as config.yaml in that directory, then run the appropriate command. If the config uses relative paths, set the correct data directory with -d and keep the related files in the expected locations.
# Windows PowerShell
.\mihomo.exe -t -f .\config.yaml
# macOS / Linux
./mihomo -t -f ./config.yaml
-t tests the config; it does not verify every remote rule set, node connection, or runtime permission. If the log points to a specific line, check the line before it too: a missing colon, tab indentation, or incorrect list nesting may only trigger a parser error on the next line.
Use a minimal config only to isolate the issue
This config checks whether the core can complete a basic startup. It contains no proxy nodes and sends all matched traffic directly. Save it as a separate test file and restore your original config afterward. Do not mistake it for a working proxy subscription.
mixed-port: 17890
allow-lan: false
mode: rule
log-level: info
rules:
- MATCH,DIRECT
If the minimal config starts but your original config does not, check node protocols, policy group references, rule-set paths, and the results of any overrides. If the minimal config also fails, continue by checking ports, the core file, and the system environment. Make sure port 17890 in this example is not already in use.
Resolve port conflicts: identify the process listening on the port
A common setup uses 7890 for the mixed proxy port and 9090 for the controller port, but these are not fixed values across all clients. Check the logs and final config for the actual ports. HTTP, SOCKS, and DNS listener ports can also conflict.
Find a listening PID on Windows
Get-NetTCPConnection -State Listen -LocalPort 7890,9090 |
Select-Object LocalAddress,LocalPort,OwningProcess
Get-Process -Id 4321
The 4321 in the second command is an example PID; replace it with the value returned by the first command. If it belongs to an old client, quit from its system tray menu first. If it belongs to another service, check what it does before stopping it. Use an administrator terminal only if you need elevated access to view the full details.
Check ports on macOS and Linux
# macOS
lsof -nP -iTCP:7890 -sTCP:LISTEN
lsof -nP -iTCP:9090 -sTCP:LISTEN
# Linux
ss -lntp
These commands check TCP listeners. If the error involves a DNS listener on UDP, also run lsof -nP -iUDP:1053 or, on Linux, ss -lnup, replacing 1053 with the actual port. After changing a port, update your system proxy settings, browser extensions, and command-line proxy environment variables too. Otherwise, the client may start successfully while your apps still cannot connect.
Core files and TUN permissions: fix the specific failure
An interrupted upgrade, a file quarantined by security software, or a read-only install directory can leave the client unable to find its core. Check the logs for the actual core path, then confirm that the file exists. Do not rename an arbitrary downloaded binary and drop it in its place: the client may rely on specific launch arguments, controller behavior, or companion files.
- Windows: Open Windows Security → Virus & threat protection → Protection history and check for a related entry. Verify the source and alert details before deciding what to do; do not disable protection globally. For an installed app, repair it with the original installer. For a portable build, try extracting it to a new directory your user account can write to.
- macOS: Make sure the installer matches your Apple silicon or Intel Mac. If macOS explicitly says the app was blocked, verify its source, then check the relevant options under System Settings → Privacy & Security. Do not remove security attributes in bulk from your entire Downloads folder.
- Linux: Run
uname -mto check your system architecture andfile ./mihomoto inspect the core binary. If the file exists but will not run, check the dynamic loader, mount options, and architecture instead of assuming it is simply a permissions problem.
On Linux, run chmod u+x ./mihomo only after confirming the file is trusted and genuinely lacks its execute bit. Do not recursively grant broad permissions to your home directory, and do not run the graphical app as root long-term to work around a data-directory permission issue.
Isolate failures that start when you enable TUN
Turn off TUN and start only the core and local proxy ports. If proxy mode works but enabling TUN triggers device creation, routing, or permission errors, focus on the virtual network interface and privileged service. Windows clients typically use administrator access or a service mode; macOS may require a helper app; Linux often needs access to /dev/net/tun and network-management permissions. The setup steps vary by client version, so use the service installation process provided for your version.
Pause other VPNs or TUN clients and test again to avoid multiple tools changing the default route. After fixing the issue, verify proxy mode first, then enable TUN. Avoid changing DNS, routes, and the subscription all at once, or you will not know which change helped.
UI runtime: WebView2, Electron, and system components
If the core can start on its own but the window is blank or disappears immediately, check the UI runtime. Clients use different technologies: some Windows clients rely on WebView2, while others use Electron or Flutter. Reinstalling WebView2 just because an app has “Clash” in its name may have nothing to do with the problem.
- Check the client’s dependencies. Review the installation instructions and system requirements for your version. For a Windows client that explicitly requires WebView2, search for Microsoft Edge WebView2 Runtime under Settings → Apps → Installed apps. The location may vary between Windows versions.
- Repair it using the official process. Use the WebView2 Runtime installer distributed by Microsoft to repair or reinstall it, then restart the client. Do not download individual DLLs from unknown sites and copy them into the app folder.
- Check the faulting module. For Electron or Flutter clients, use their logs to investigate runtime libraries, graphics drivers, and app resources. Disable hardware acceleration only if the client documentation explicitly supports it; do not copy launch flags from a different client.
On Linux, WebKitGTK, the graphics session, and shared-library dependencies vary by package type. First use a terminal to identify the missing library, then install it with your distribution’s package manager. Do not mix in libraries from another distribution. On macOS, first confirm that your system version meets the installer’s requirements before reinstalling the client.
Isolate the data directory while keeping the old state recoverable
Try fresh user data only after config checks, port checks, and runtime repairs have failed. Uninstalling and reinstalling may leave the user data directory untouched, so “it still crashes after reinstalling” does not prove the installer is at fault.
- Exit all related processes. If a background service is still writing data, stop it using a method supported by the client to prevent files from changing during the backup.
- Find the actual data directory. Use the logs, documentation, or the client’s directory shortcut to locate its data. Do not confuse the install directory, system cache, and user config.
- Copy and rename the directory. Back up the entire directory first, then rename the original with a dated name, such as
client-data-backup-20260929. Do not permanently delete it right away or upload the whole directory publicly. - Start with a clean state. Do not import a subscription or enable TUN. Once the UI and core both work, restore subscriptions, custom rules, overrides, and preferences one at a time.
If the clean state works but the client fails after you restore an item, keep a minimal copy that reproduces the issue. Do not copy the entire old directory back, or you may restore corrupted state files as well. If the client still fails with clean data while the same core runs on its own, report the UI crash details rather than continuing to change proxy rules.
Verify the fix and prepare a useful bug report
Getting the window to open is only the first step. After the fix, verify that the core stays running, the expected ports are listening, and the subscription loads without another crash when you enable the features you need. Test system proxy and TUN separately, and check that your original system proxy settings are restored as expected.
- Startup check: Start and exit the client normally twice. Confirm that no leftover process is still holding the same port after exit.
- Config check: Update the subscription manually once, then check the final config test and rule-set loading results. If the update fails, keep the old config rather than overwriting your only working copy.
- Mode check: Test the local proxy first, then the system proxy, and finally enable TUN if needed. Check the logs at each step.
- What to include in a bug report: OS version, architecture, client and core versions, reproduction steps, the first error, and redacted logs. Say whether the client starts with a minimal config and a fresh data directory.
When reporting the issue, details like “exits two seconds after an upgrade; minimal config works; issue returns when a particular override is restored” are much more useful than a screenshot of an error dialog alone. After troubleshooting, restore the log level to your normal setting, keep a safe backup of the working config, and remove temporary diagnostic files that contain sensitive information.