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 shows match 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. Confirm dns.enable: true in 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 change mixed-port to 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 switching tun.stack between 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

  1. Switch the log level to debug and reproduce the issue once, so the error shows up fresh at the end of the log.
  2. 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.
  3. 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.
  4. 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
  1. 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 keywordStageLikely causeNext step
connection refusedNode connectionNode offline, wrong portSwitch node, update subscription
i/o timeoutNode connectionBlocked route, server downSwitch network to cross-check
connection reset by peerNode connectionNode overloaded, transport interfered withSwitch node and see if it recurs
x509: certificate has expiredTLS handshakeSystem clock inaccurateSync clock and retest
not look like a TLS handshakeTLS handshakeWrong port or protocol typeCheck subscription node parameters
message authentication failedProtocol authenticationPassword or cipher mismatchCross-check against subscription source
yaml unmarshal errorsConfig loadingSyntax errorCheck indentation and quoting by line number
proxy provider errorSubscription updateDead link, needs proxy to updateEnable proxy for updates or switch link
dns resolve failedDNS resolutionUpstream unavailableCheck dns config
address already in useLocal portPort conflictClose old process or change port
permission denied(TUN)TUN startupInsufficient permissions, missing driverRun 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.

Download Client