Skip to content

How to Read Clash Logs: Common Errors Explained, from dial tcp to i/o timeout

Learn how to change log levels and interpret common Clash errors like dial tcp, i/o timeout, and connection refused. Trace log entries to nodes, rules, or DNS.

1. Reproduce the issue, then check logs from that moment

If a website won’t load, don’t start by changing DNS, nodes, TUN, and rules all at once. Open the client’s Logs page, note the current time, and reload the affected page once. Check the entries from a few seconds around that moment instead of picking the scariest-looking error from a screen full of red text.

Log colors indicate severity, not the scope of a problem. A failed background latency test may generate a warning while your browser connection still works. Conversely, a bad direct-connection rule may show only a routine connection entry, with no prominent error.

  1. Note the client name and version, the core name, and whether the current mode is Rule, Global, or Direct.
  2. Record the failed domain, the time, and what happened—for example, the homepage loads but images do not.
  3. Clear the log view or filter by time, then repeat the same action once. Clearing the view does not necessarily delete log files from disk.
  4. Keep the entries around the failed request, especially the destination, matched rule, outbound policy, and error details.

2. Changing the log level: start with info, enable debug only briefly

Clash clients usually show runtime logs in the Logs section of the sidebar. If the page offers a level filter, check whether it only filters displayed entries or also changes the core’s log level. Setting the filter to Debug alone may not make the core emit debug output.

The configuration field for controlling log verbosity is log-level. Both the original Clash and mihomo use this field. If the client has a Log Level setting, change it there first. If not, use the configuration override or merge feature supported by the client. Don’t assume that editing a subscription-generated file will persist—the next subscription update may overwrite it.

# Place this at the top level of the config; do not indent it under dns or rules
log-level: info
LevelUse caseNotes
silentSuppresses routine log outputSwitch to a different level when troubleshooting
errorShows errors onlyMay omit rule matches and connection context
warningShows warnings and more severe issuesUseful for quickly spotting repeated connection failures
infoA good starting point for everyday troubleshootingRead alongside the destination and outbound policy
debugAdds details about DNS lookups, connections, and moreReproduce briefly, then switch back to avoid excessive logs

When you need debug output, temporarily set this field to debug, reload the config or restart the core as required by your client, reproduce the issue once, then restore it to info. The configuration field uses warning, but log entries may label the level as WARN or warning. Don’t confuse the two.

Before sharing logs, check for subscription links, access tokens, node passwords, server addresses, and local file paths. Keep the original error and port structure, but don’t post your entire subscription config when asking for help publicly.

3. Check four things in a connection log: destination, rule, outbound, and error

[info] [TCP] 127.0.0.1:53142 --> www.example.com:443
match DomainSuffix(example.com) using Proxy[Node-A]

This simplified entry means an app on your device sent a TCP request from temporary port 53142 to www.example.com:443. A domain-suffix rule matched, and the Proxy policy group selected Node-A for the outbound connection. The temporary port on the left is not the client’s proxy listening port; you don’t need to change any settings to match it.

MATCH usually means the request reached the fallback rule; it doesn’t mean the rule engine failed. If a site that should use a specific policy reaches the fallback instead, check whether an earlier rule covers the domain, whether the rule set loaded, and whether the expected config is active.

4. dial tcp: a TCP connection is being made; check the details that follow

dial tcp describes an attempt to connect; it is not a diagnosis on its own. It’s usually followed by an address and the underlying error. Both examples below contain this phrase, but call for different troubleshooting steps:

dial tcp 203.0.113.10:443: i/o timeout
dial tcp 127.0.0.1:7897: connect: connection refused

Remote address failures: identify what the address belongs to

The remote address in the first example could be a proxy server or the destination website for a direct connection. Check the outbound field and config to tell which. If it matches the current node’s server address, investigate the connection from your device to that node first. If it’s a website being accessed via DIRECT, check your local network, routing, and the site itself.

Local address failures: check the listening port first

The second example points to 127.0.0.1:7897 on your device. If this is the proxy address used by your browser or command line, a refused connection usually means no service is listening there or the service failed to start. 7897 is just an example, not a default for every client.

Check the actual Mixed Port or HTTP/SOCKS port shown in the client. If a mixed port is enabled, its configuration field is mixed-port. On Windows, run this command to check whether the example port is listening:

netstat -ano | findstr :7897

Check the local address and LISTENING status in the output, then verify the process PID. A remote connection entry containing that port number does not prove that anything is listening locally. If the client failed to start, fix the startup error before switching nodes.

5. i/o timeout: a wait timed out—it doesn’t automatically mean the node is down

i/o timeout means a network read or write did not finish before its deadline. It can occur while establishing a TCP connection, querying DNS, completing a proxy handshake, or reading data after a connection is established. Those two words alone can’t tell you whether the cause is the ISP route, a remote service, UDP packet loss, or your local firewall.

  1. Identify what timed out. A timeout from a node server and one from a DNS server involve different parts of the connection. Keep prefixes such as read udp and dial tcp.
  2. Try another node on the same network. Change only the node selected in the policy group, leave rules, DNS, and TUN settings as they are, then test the same destination.
  3. Try another network with the same node. For example, switch from Wi-Fi to a mobile hotspot and see whether the same kind of timeout goes away.
  4. Check whether it affects every site or just one. If only one domain fails, check the site’s status and which rule it matches.

If multiple destinations fail only with the same node, check that node or the route to it first. A single background latency-test timeout while web requests work is not a reason to reset the entire config. The test URL and protocol may differ from your actual traffic.

6. connection refused: handle a refused connection differently from a timeout

connection refused usually means the connection request received an explicit refusal, rather than getting no response at all. Common causes include no service listening on the destination port or a device policy actively rejecting the connection. It doesn’t mean the password is wrong; password or protocol mismatches usually occur during authentication or the handshake, after the connection is established.

If the log shows address already in use, that means something different: the client tried to listen on a port that is already occupied. Find the process using it, then decide whether to close the existing instance or change the port. If you change it, update the proxy settings in any apps you configured manually.

7. DNS errors: distinguish node hostnames from website domains

no such host usually means a domain lookup returned no usable result. The name may not exist, may be misspelled, or there may be a problem with the resolution path. server misbehaving usually means the resolver returned an error status. When you see these messages, first identify the exact name being resolved instead of replacing the entire DNS config.

lookup www.example.com: no such host
read udp 192.168.1.20:53000->192.168.1.1:53: i/o timeout

The second example shows a UDP read timeout while querying 192.168.1.1:53, so focus on the DNS query path. With DoH, you may instead see connection or TLS errors to port 443 on the resolver. Don’t limit troubleshooting to traditional UDP port 53.

Node server hostname fails to resolve

If the node’s hostname can’t be resolved, the proxy handshake can’t even begin. mihomo’s proxy-server-nameserver field can specify a resolver for proxy server hostnames, but it requires a compatible version and config syntax. Don’t copy it into an older core that doesn’t support it. First confirm which core is running, then check whether its current resolver is reachable before the proxy connection is established.

Only the destination website fails to resolve

Check whether config such as nameserver-policy affects the domain, and whether the client is actually handling DNS for the app. Browser Secure DNS, built-in app resolvers, the system cache, and TUN DNS hijacking can all send queries along different paths.

With Fake-IP enabled, seeing a mapped address within a configured range such as 198.18.0.0/16 in the logs does not automatically mean DNS has been poisoned. Check the domain mapping and outbound result as well. System nslookup only shows the resolution path used for that particular query; by itself, it can’t prove that the browser or core used the same resolver.

8. Other common messages: TLS, EOF, and startup failures

Log messageWhat it means and what to check first
TLS handshake timeoutThe TLS handshake did not finish in time. First identify whether the handshake was with a node, destination website, or DoH service, then check the route and protocol settings.
x509: certificate has expired or is not yet validCheck the system date, time, time zone, and the peer certificate’s validity period. Don’t hide the cause by skipping certificate verification.
EOF / unexpected EOFThe connection closed, or a read ended unexpectedly. Check whether it happens consistently, along with the protocol and context; this alone does not prove that traffic was blocked.
connection reset by peerThe connection was reset. The cause may be the remote host, an intermediary network device, or a protocol mismatch. Compare with other nodes and networks.
network is unreachableCheck local routes, network interfaces, and IPv6 connectivity, especially after waking from sleep, switching networks, or starting or stopping TUN.
Parse config errorFix the config parsing error first. Check YAML indentation, field types, and whether the current core supports the protocol mentioned in the following message.

The original Clash, Clash Meta, and later mihomo releases do not support exactly the same configuration features. If a subscription includes a protocol or field unsupported by the current core, the error occurs while loading the config; switching nodes usually won’t help. Confirm that the config loaded and the proxy groups were created before investigating connection timeouts.

A TUN startup failure may also involve permissions, a virtual network adapter, or route creation. System proxy and TUN traffic can behave differently. Don’t assume TUN is working just because your browser can connect through the system proxy, and don’t remove system network components as soon as you see a TUN error.

9. Worked example: trace a timeout to the node connection

Suppose a browser request to www.example.com fails and the log shows this simplified entry at the same time:

[warning] [TCP] dial Proxy (match DomainSuffix/example.com)
127.0.0.1:53142 --> www.example.com:443
error: dial tcp 203.0.113.10:443: i/o timeout
  1. Confirm it’s the same request. The destination domain and timestamp match the action, so this is not a background latency test.
  2. Confirm the rule is expected. The log shows Proxy. If you intended to use a proxy, leave the rules unchanged for now.
  3. Check the address that failed. Suppose the current node’s server address is 203.0.113.10:443. The evidence points to a timeout connecting to the node, not an HTTP error returned by the website.
  4. Switch only the node. Select Node-B, keeping the mode and destination unchanged. If the request succeeds, investigate Node-A or the route to it first.
  5. Test on another network if needed. If Node-A works on a hotspot but keeps timing out on your usual network, the issue is more likely related to the original network path, though this doesn’t identify which device is blocking it.

If the original entry instead shows using DIRECT, the node-related conclusion above does not apply. First find out why the request went direct, then check its rule and outbound in the client’s Connections page. You can temporarily switch to Global mode for comparison, but restore the original mode afterward and fix the rule. Global mode is not a long-term fix for every problem.

10. No log entry? Check the traffic path first, and keep key evidence when asking for help

If reloading the page produces no corresponding entry, suspect that traffic never reached this core or that the log view filtered it out. Check whether the app uses the system proxy, whether a browser extension overrides proxy settings, whether another VPN is connected, and whether TUN actually started. Enabling the system proxy alone does not guarantee that every app or UDP flow will pass through Clash.

You can also test the local mixed port directly. Replace 7897 in the command below with the port shown in your client. In Windows PowerShell, use curl.exe to avoid differences caused by an older alias with the same name.

curl.exe -I --proxy http://127.0.0.1:7897 https://example.com

Check the logs immediately after running the command. If it reports that the local port refused the connection, check whether it is listening and whether the core is running. If a destination connection entry appears, investigate the rule, outbound, and error in that order. The HTTP status only describes this request; it does not replace checks for other apps.

Include this information when reporting a problem

Follow the same order every time: confirm traffic reaches the core, check the rule and outbound, then pinpoint DNS, connection, or handshake issues. Change one variable at a time and record the result. Once access works again, switch the log level back from debug. That way, when the same error appears again, you can build on what you already know instead of trying every toggle from scratch.

Clash downloads