Reading Clash Logs: Common Error Messages Explained
When a connection fails, check the logs first. Common Clash log entries are grouped by error keyword, explaining which stage each one points to and where to look next.
When the client can't connect, the usual first reaction is to flip the system proxy toggle a few times and click through nodes blindly. But the core's log has already spelled out the reason for the failure in fairly specific terms — it's just compact and mostly in English, so a lot of people glance at it and close the window. This article groups common log entries into five categories by error keyword, explaining what stage each one occurs at, what usually causes it, and what to check next.
Understanding a log line's structure first
The log format from the Clash core (including Clash Meta / mihomo) is fairly consistent. Take a typical TCP entry as an example:
[TCP] 127.0.0.1:52310 --> www.google.com:443 match DomainSuffix(google.com) using Node Select[HK 01]
Break it down and there are five fields:
[TCP]/[UDP]: the transport protocol for this connection. Most web browsing is TCP; QUIC, and some games and voice calls, use UDP.127.0.0.1:52310: which local source initiated the connection. Under system proxy mode this is usually 127.0.0.1; under TUN mode you'll see a more specific LAN source address.--> www.google.com:443: the destination address and port. If this shows an IP instead of a domain, the app is connecting directly by IP, which means domain-based rule matching won't apply to it.match DomainSuffix(google.com): the rule that matched. If it showsmatch Match(), the traffic fell through to the final catch-all rule — nothing above it matched.using Node Select[HK 01]: the actual outbound path. If it shows DIRECT, this traffic isn't going through the proxy — if a target that should be proxied shows DIRECT, the issue is in your rules, not the node.
Log verbosity is controlled by log-level in the config, with options silent, error, warning, info, debug — most clients default to info. When troubleshooting, switch to debug first to see DNS queries, rule-matching details, and the handshake process:
log-level: debug
GUI clients (Clash Verge Rev, Clash for Windows, etc.) all have a log panel where you can switch levels directly; for core-only deployments, logs go to standard output, and once external-controller is configured you can also pull logs in real time via the controller's /logs endpoint.
Note
Debug-level logging generates a large volume of output and records full traffic details. Switch back to info once you're done troubleshooting — otherwise the flood of debug output will bury the information you actually need.
Errors during the node connection stage
If "dial" appears in the log, Clash is attempting to connect to the node server — the problem is somewhere between your machine and the node.
[TCP] dial HK 01 --> www.google.com:443 error: dial tcp 198.51.100.7:443: connect: connection refused
connect: connection refused: the server actively rejected the connection — nothing is listening on that port. Common causes: the node is offline, the port was changed, or the subscription info is stale. Try another node from the same subscription first; if all of them fail, update the subscription.i/o timeout/context deadline exceeded: the connection timed out with no response at all. Compared to "refused," this looks more like a blocked route or a dead server. Switch from Wi-Fi to a phone hotspot and test again to quickly tell whether it's your ISP or the node.connection reset by peer: the connection was established but then cut off midway by the other side. A one-off occurrence can be ignored; if it keeps happening, the node is likely overloaded or the transport is being interfered with.
This stage has nothing to do with your local proxy settings — once "dial [node]" already appears in the log, traffic has successfully reached Clash, so there's no need to keep fiddling with the system proxy toggle.
Errors during TLS and protocol handshake
The connection to the server succeeded but the handshake failed — expect keywords like tls, x509, EOF.
x509: certificate has expired or is not yet valid: certificate time validation failed. Check your system clock first — nearly all TLS-based protocols fail if the time is off by too much. If system time is correct, then suspect the node's certificate configuration.tls: first record does not look like a TLS handshake: whatever is running on that port isn't a TLS service. Usually the port or protocol type in the subscription is wrong — for example, a Trojan node pointed at a non-TLS port.EOF/tls: handshake failure: the connection was cut mid-handshake. Common when SNI or ALPN doesn't match the server — check whether the servername / sni field in the node config has been altered.- Shadowsocks reporting
cipher: message authentication failed: AEAD verification failed — the password or cipher doesn't match the server. Cross-check both against the subscription source. - VMess node config looks correct but authentication still fails: check your system clock. VMess uses timestamp-based verification, and if local time drifts too far from the server's, requests get rejected.
- WebSocket-based nodes reporting
websocket: bad handshake: the path or Host header doesn't match what the server expects — especially common after a CDN origin config change.
Handshake-stage errors are largely unrelated to local network quality — they boil down to two things: whether node parameters were changed, and whether subscription info is stale.
Errors during config and subscription loading
These errors show up when starting the core or updating a subscription, with keywords like yaml, unmarshal, proxy provider.
yaml: line X: .../unmarshal errors: a syntax error near line X of the config file. YAML doesn't allow tab indentation, colons must be followed by a space, and values with special characters need quotes. Just check that line number.proxy [xxx] not found: a proxy group references a node that doesn't exist. Usually happens after renaming or deleting a node without updating the group — just align the reference name.rules[X] ... error: rule number X failed to parse. Common causes are a misspelled rule type or a wrong number of parameters, such as forgetting the destination policy at the end.proxy provider ... error, or a subscription update returning 404 or timing out: the subscription link is dead, or the subscription URL simply isn't reachable on your current network. Most clients have an "update subscriptions via proxy" toggle — if the subscription URL needs a proxy to reach, turn that on before updating.
When config loading fails, the core usually exits immediately or refuses to start, which actually makes this category the easiest to pinpoint — the error message gives you a specific line number or field name to fix directly.
DNS, port conflicts, and TUN errors
dns resolve failed, or DNS queries timing out: Clash's built-in DNS isn't configured correctly, or the upstream server is unreachable. Confirmdns.enable: truein the config and that the nameserver list has a reachable upstream; if fake-ip mode is misbehaving, switch back to redir-host to check whether it's a fake-ip caching issue.
dns:
enable: true
nameserver:
- 223.5.5.5
- 119.29.29.29
bind: address already in use, or failing to listen on 7890: the mixed port is already taken. Usually another core process or similar app is still running — just close it; you can also changemixed-portto a different port, but remember to update the port in your system proxy settings too.- TUN mode fails to start (
permission denied, or the utun / wintun device can't be found): TUN needs admin privileges, and Windows also depends on the wintun driver. Run the client as administrator; if it still fails, try switchingtun.stackbetween system and gVisor — some stacks aren't compatible with certain OS versions. - System proxy fails to apply: on macOS this needs authorization to change network settings; on Windows, check whether security software is blocking the proxy toggle from writing changes.
A fixed troubleshooting sequence
- Switch the log level to debug and reproduce the issue once, so the error shows up fresh at the end of the log.
- Scan from the bottom up for the first error or warning — don't fixate on the very last line, since everything that follows the first error is often just a chain reaction from it.
- Sort that first error into one of five stages by keyword: config loading, subscription update, DNS resolution, node connection, or protocol handshake — then follow the relevant section above.
- Cross-check by bypassing the system proxy and testing the Clash port directly:
curl -x http://127.0.0.1:7890 https://www.google.com -I
- If it works, the core and node are fine and the issue is in the system proxy or browser; if it doesn't, the problem is between the core and the node. Change one thing at a time and retest — change three things at once and you'll never know which one actually fixed it.
Tip
Logs contain node addresses, visited domains, and similar info. Before posting a log in a group or forum to ask for help, remember to redact node IPs, domains, and subscription links.
Error keyword quick reference
| Error keyword | Stage | Likely cause | Next step |
|---|---|---|---|
connection refused | Node connection | Node offline, wrong port | Switch node, update subscription |
i/o timeout | Node connection | Blocked route, server down | Switch network to cross-check |
connection reset by peer | Node connection | Node overloaded, transport interfered with | Switch node and see if it recurs |
x509: certificate has expired | TLS handshake | System clock inaccurate | Sync clock and retest |
not look like a TLS handshake | TLS handshake | Wrong port or protocol type | Check subscription node parameters |
message authentication failed | Protocol authentication | Password or cipher mismatch | Cross-check against subscription source |
yaml unmarshal errors | Config loading | Syntax error | Check indentation and quoting by line number |
proxy provider error | Subscription update | Dead link, needs proxy to update | Enable proxy for updates or switch link |
dns resolve failed | DNS resolution | Upstream unavailable | Check dns config |
address already in use | Local port | Port conflict | Close old process or change port |
permission denied(TUN) | TUN startup | Insufficient permissions, missing driver | Run as administrator |
The log is Clash's first-hand testimony. Read it before you start changing things — once you lock in a fixed troubleshooting sequence, most connection issues can be traced to a specific stage within minutes.
Download the Clash Client
Clash clients are free and open source across Windows, macOS, Linux, and Android. Pick the version for your platform, pair it with a subscription link, and you're ready to go.