Why logs are the first line of evidence in troubleshooting
Clash-family clients (including the original core and the mihomo core) continuously output structured text logs at runtime, recording the execution results of every step — connection establishment, rule matching, DNS lookups, proxy selection, and so on. Compared with a vague symptom description like "the internet isn't working," logs give you the exact failure reason for a specific connection or a specific query. This is exactly why official documentation and community troubleshooting workflows keep repeating "check the logs first."
Most clients (Clash Verge, derivatives of Clash for Windows, mihomo party, and others) provide a "Logs" tab on the main interface, and some also support filtering by level and searching by keyword. When running the core from the command line, logs are printed directly to standard output, and can also be routed to a specific file via the log-level field in the config file. Regardless of which client you use, understanding the log format and common error types lets you shrink troubleshooting time from "restart repeatedly and hope for the best" to "pinpoint the exact step."
How to set the log level, and which level to watch
The log-level field in the Clash config file determines how detailed the output is. Common values, from coarse to fine, are:
- silent: No output at all. Only used for fully silent production runs — don't use this level when troubleshooting.
- error: Only records serious problems such as connection failures and config parsing errors. Minimal information, and it's easy to miss intermediate steps.
- warning: Adds potential-issue notices on top of error, such as slow rule set loading or certificates about to expire.
- info: The default recommended level. Records proxy selection results, DNS query summaries, and connection open/close events — a moderate level of detail that's sufficient for everyday troubleshooting.
- debug: Outputs the fullest execution detail, including the matching attempt for every single rule and a byte-level summary of protocol handshakes. Turn this on temporarily when digging into a tricky issue; it's not recommended for long-term use since it produces a large volume of logs and may affect performance.
Configure it in your YAML config file like this:
log-level: info
When troubleshooting a specific error, it's best to temporarily switch the level to debug, reproduce the issue, and then switch back to info — otherwise you'll end up with an oversized log file eating disk space over time.
High-frequency errors, one by one
DNS resolution failures
These logs typically contain dns resolve failed, no such host, or similar wording, meaning the client tried to resolve a domain name into an IP address and failed. Common causes include:
- The DNS server address in the config file is wrong or that server has stopped working;
fake-ipmode is enabled, but the target domain was mistakenly placed in the direct-connect group, so the real DNS request never went through the proxy channel;- When using encrypted DNS over DoH/DoT, the upstream encrypted DNS server itself needs to be reached through the proxy, creating a chicken-and-egg deadlock;
- The domain itself doesn't exist or has expired — this is a domain-side problem, not a client-side one.
How to trace it: first confirm whether the nameserver field in the config points to a valid address, then check whether the rule group matching that domain routes to the expected node. If it's an encrypted-DNS deadlock, you can configure the DNS server address to go direct on its own, or point it at a stable, known-working exit node.
Handshake timeouts
When the log shows handshake timeout, dial tcp: i/o timeout, or context deadline exceeded, it means the client attempted to connect to a proxy node but failed to complete the TLS handshake or TCP connection within the allotted time. The causes generally fall into three categories:
- Node side: the server is offline, the port has been temporarily blocked, or the server's network region is having quality issues;
- Protocol parameter side: the encryption method or transport protocol (e.g. WebSocket path, gRPC service name) configured on the client doesn't match the server, so the handshake request format is rejected by the far end;
- Local network side: the local outbound network is throttling or interfering with the target port — a common pattern with certain ISPs' QoS policies targeting specific ports.
How to trace it: test with another node under the same subscription first. If every node times out, the problem is very likely on the local network side; if only a specific node times out, suspect that node's status or its protocol parameters first.
Rule mismatches
When the log shows match RuleSet(...) or final rule but traffic doesn't route the way you expected, this isn't actually an error — the rule matching logic did fire, just not into the group you had in mind. Common causes:
- Rules are matched top-down, and a broader rule above catches the traffic first, so a more specific rule further down never gets a chance to run;
- The rule set (rule-provider) wasn't refreshed in time and is still using an outdated domain/IP list;
- The final catch-all rule (
MATCH) points to an unexpected group, and all traffic that didn't match anything earlier ends up there.
How to trace it: turn on debug-level logging, make a single connection to the specific domain in question, search the logs for that domain, and see exactly which rule it matched and which proxy group it landed in. Then cross-check that against the rule file's ordering line by line.
Connection refused and protocol errors
connection refused means nothing is listening on the target port — usually because the port configured on the server doesn't match what the client has, or the server-side service hasn't started. Protocol-layer errors like invalid header or unexpected EOF most often point to a mismatch in encryption method or obfuscation parameters (such as obfs type) between client and server, which requires checking each protocol field in the subscription one by one.
A practical path for tracing problems by error type
Once you have an error log in hand, it's best to narrow things down in the following order rather than trying every possible cause one at a time:
- Step one, identify which stage the error occurred in. Was it during DNS resolution, during the handshake, or during rule matching? Keywords in the log (resolve / dial / handshake / rule) usually already indicate the stage, and sorting by stage first eliminates most of the irrelevant directions.
- Step two, determine whether it's a single-node problem. Switch to a different node under the same subscription and retry. If the problem disappears, it's that node's server-side status or parameters; if it persists, move to step three.
- Step three, determine whether it's a local network problem. Temporarily disable the proxy and access the target site directly, or test from a different network such as a phone hotspot, to rule out interference from your local ISP or router policy.
- Step four, review the config file itself. Check the DNS settings, rule order, when the rule-provider was last updated, and whether the subscription is current — many "apparent node problems" turn out to be an outdated config file or a typo in a field.
- Step five, raise the log level and reproduce the issue. If the first four steps haven't found the source, temporarily set
log-levelto debug, fully reproduce the failure once, and save the relevant log snippet for further analysis or for posting when asking the community for help.
A few practical habits for everyday log reading
- When a connection fails, look at the timestamp first to pinpoint the exact moment of failure, then work backward and forward a few seconds through the log context, rather than scrolling aimlessly through a long log.
- Make good use of the client's log-page keyword filter — search directly for the domain or IP that's causing trouble to quickly surface every relevant log line.
- After changing rules, it's worth running a debug-level check once to confirm the new rules actually take effect as expected, then switch back to info level for regular operation.
- TUN mode issues often involve both the system network stack and the core's own logs. If TUN mode won't connect, in addition to checking Clash's own logs, also watch for any separate TUN status indicator the client provides.
- Keep a backup of the config file from the last time everything worked normally. If errors suddenly increase after an upgrade, you can directly diff the config to pinpoint what changed.
Once you've got a handle on reading logs, most connection issues can be traced to the exact step within minutes, without having to try every possible fix one by one.