1. Open the Logs First: Three Access Points
Let's get practical. No matter which client you use, the logs all come from the same place — the core. The GUI just subscribes to the core's output, so the error text you see is identical across clients; learn to read the text, and you've effectively learned all of them. Access points fall into three categories:
- The log panel in your GUI client. Clash Verge Rev has a "Logs" entry in the left sidebar that shows a real-time scrolling feed of core logs, with a level filter at the top; Clash for Windows has an equivalent "Logs" section with the same filtering support.
- The log-level setting in the core config. When running the mihomo core directly, logs print to the terminal, and verbosity is controlled by the
log-levelfield in the config file. It accepts five values —silent,error,warning,info,debug— defaulting toinfo. - The external controller API. Once the core enables
external-controller(commonly at127.0.0.1:9090), the/logs?level=infoendpoint streams logs continuously — this is the channel your GUI's log panel actually reads from.
Note: switching the filter level in the interface only changes what's displayed, not what the core actually records. To get more detailed logging from the core, change log-level and restart the core (or reload the config) for it to take effect.
2. Anatomy of a Log Line: Timestamp, Level, Connection
Start with a typical info-level log line (formatting varies slightly between clients, but the components are the same):
2026-06-19 21:03:11 INFO [TCP] 127.0.0.1:52341 --> www.example.com:443 match DomainSuffix(example.com) using HK Node
Break it into four parts:
- Timestamp
2026-06-19 21:03:11: use this first to line up with the exact moment you performed the action — anything logged before that moment is unrelated to your current issue; - Level
INFO: from lowest to highest, the order is debug, info, warning, error — the higher the level, the more worth stopping to read; - Connection
[TCP] 127.0.0.1:52341 --> www.example.com:443: the left side is the local source address and ephemeral port, the right side is the destination and port being accessed; - Result
match DomainSuffix(example.com) using HK Node: which rule this connection matched and which outbound it was handed to — the outbound can be a proxy node, DIRECT, or REJECT.
Here's why the format looks like this. Clash's core model is "a connection comes in, it's checked against the rule set, then handed to an outbound" — so nearly every runtime log line follows this pattern. Reading logs really just means checking three things: is the destination correct, did the right rule match, and is the outbound correct. Only once all three check out and things still don't work should you start suspecting the node or the network path.
3. Five Common Errors, Explained One by One
1. Connection Timeout: i/o timeout
2026-06-19 21:04:02 WARN [TCP] dial HK Node 127.0.0.1:52341 --> www.google.com:443 error: dial tcp 203.0.113.8:443: i/o timeout
What it means: the core reached out to the proxy server and got no response before timing out. context deadline exceeded is just another form of the same error. Troubleshoot in this order — node, then network path, then local machine:
- Run a latency test across your node list: if everything times out, it's likely an expired subscription or no local internet; if just one node times out, that node is the problem;
- Switch to a different node and try the same destination — if it works, the original node is confirmed dead;
- If every node fails, try the same destination via DIRECT once — if direct connection also fails, the fault lies with your local network itself.
Why: a timeout only tells you "no response was received" — it doesn't distinguish between a dead node, an interfered-with route, or a local outage. That's why you need to rule things out layer by layer instead of jumping straight to reinstalling the client the moment you see a timeout.
2. Subscription and Config Parsing Failures
2026-06-19 21:05:40 ERROR configuration file error: yaml: unmarshal errors: line 86: cannot unmarshal !!str into map[string]interface {}
What it means: the YAML structure around line 86 of the config file is malformed, so the core refuses to start. Three common causes: broken indentation after manual editing; the subscription URL returning an HTML error page instead of YAML; or the config containing fields the current core doesn't recognize. Another common variant:
2026-06-19 21:05:41 ERROR proxy 3: unsupport proxy type: hysteria
What it means: the fourth node (counting from 0) uses a protocol the core doesn't support. The original Clash core doesn't recognize newer protocols like hysteria or tuic — you'll need a client built on the mihomo (Clash Meta) core instead. The client comparison page lists which core each client uses.
Troubleshooting order: if the error gives a line number, go straight to that line; if it gives a node index, count to that node. When a subscription import fails, paste the subscription URL directly into your browser — garbled text or an error page means the subscription itself is broken; a large chunk of readable text means the problem is in the client's parsing step instead.
3. Port Conflict: bind error
2026-06-19 21:06:15 ERROR start mixed(http+socks) proxy error: listen tcp 127.0.0.1:7890: bind: address already in use
What it means: the core wants to listen on port 7890, but another process is already using it, so the proxy service can't start. On Windows, the same error reads "Only one usage of each socket address is normally permitted." Troubleshoot in this order:
- The most common cause is a previous Clash instance that didn't fully quit. Open Task Manager, look for leftover clash, mihomo, or clash-verge processes, end them, then restart;
- If an unrelated program is confirmed to be holding the port, change the mixed port in the client settings (e.g., from 7890 to 7897), save, and restart the core.
Why: a listening port is an exclusive resource — only one process can hold it at a time. The fix for this type of error is always the same two steps: find who's holding the port, then decide whether to close it or switch to a different port yourself.
4. DNS Resolution Failure
2026-06-19 21:07:33 WARN [TCP] dial DIRECT 127.0.0.1:52410 --> api.example.com:443 error: dns resolve failed: couldn't find ip
What it means: the core can't resolve the target domain's IP address, so the connection stalls right at the lookup step. First check whether the client's DNS settings have been misconfigured — restore the default and try again; then confirm the system itself can resolve normally (can your browser get online with the proxy off). This error is less common under fake-ip mode; if it keeps happening, add a public DNS resolver such as 223.5.5.5 or 119.29.29.29 to the DNS config as a fallback.
5. TUN Mode Fails to Start
2026-06-19 21:08:20 ERROR start TUN listening error: create tun: permission denied
What it means: TUN mode needs to create a virtual network adapter, which requires administrator privileges. On Windows, launch the client via "Run as administrator"; on macOS and Linux, follow the client's authorization prompt. If it still fails after granting permission, check for conflicts with other VPN or accelerator-type software — two virtual adapters fighting over routing will interfere with each other, so quit the other one first. The full TUN mode setup steps are covered in a dedicated section of the setup guide, and any unfamiliar terms can be looked up in the glossary.
4. A Fixed Workflow for Diagnosing Issues
Let's turn the scattered points above into one workflow. Whenever something goes wrong, follow these five steps:
- Watch the logs while reproducing the issueSet the filter level to warning or higher, and check first for any error lines.
- Identify the stageStartup errors (config parsing, port conflicts, TUN creation) show up the instant you open the client; runtime errors (timeouts, DNS, handshake failures) only appear when you actually try to visit a site.
- For startup errors, follow the text exactlyGo to whatever line the error points to — don't guess based on memory.
- For runtime errors, separate node issues from local ones firstRun a latency test to tell node problems apart from local network problems, then check the
match ... using ...line to confirm the rule match is what you expect — if a local site is being routed through a proxy node, that's usually a rule or GeoIP data issue, not a node problem. - Switch to debug if you still can't tellWhen the current level doesn't reveal the cause, temporarily switch to debug, reproduce the issue once, capture the details, then switch back to info.
Why: logs are ordered by time, but faults have a clear stage they belong to. Pinning down the stage first, then reading the text, is far faster than scrolling through thousands of lines hunting for keywords.
5. Using debug Level: How and When
How to do it: switch the level to debug in the log panel, or add log-level: debug to the config and reload the core, then reproduce the issue fully and capture the section from when you started the action to when the error appeared. Three things to keep in mind:
- debug prints matching details for every single connection, scrolls extremely fast, and will slow down the UI and bloat log files if left on for a long time;
- The logs contain domains you've actually visited — before posting a screenshot to a forum or group chat for help, black out any sensitive domains first;
- Once the issue is resolved, switch back to info so the logs stay quiet in normal operation and only speak up when something's wrong — which keeps them readable the next time you need to troubleshoot.
And that wraps up reading logs: three access points, one line format, five common errors, five-step workflow. Next time your client spins endlessly or a page won't load, don't rush to reinstall — open the logs and start with the most recent error line.