Identify the log source and connection stage first

Clash logs aren’t a simple scorecard for judging nodes. A single webpage request can involve DNS resolution, rule matching, a connection to the proxy server, a protocol handshake, and a connection to the destination. The right fix depends on where the error occurs. Switching subscriptions as soon as you spot a red entry can erase the most useful evidence.

First, distinguish client logs from core logs. Client logs usually cover the interface, configuration downloads, updates, and permissions. Clash or mihomo core logs mainly cover configuration loading, listening ports, DNS, and connection handling. A client running mihomo doesn’t mean every error comes from mihomo. Record both the client and core versions when troubleshooting—not just “the latest version.”

  • Fails at startup: Check configuration parsing, policy references, port conflicts, and permission messages first. There’s no need to start by checking the destination website.
  • Starts normally, but webpages won’t load: Find the connection entry for the domain, then check the rule and outbound route.
  • Only subscription updates fail: Check the network path used to download the configuration, the subscription URL, and the HTTP response. This doesn’t automatically mean the proxy connection is failing.
  • The browser fails, but there’s no related log: Check whether traffic is reaching the client before looking at nodes. The system proxy may not cover every app, and TUN may have route exclusions.

Adjusting log levels: start with info, then enable debug briefly

Open the client’s Logs page and look for a level dropdown or filter. Note that an interface filter may only hide some entries without changing the core’s log level. To capture more detail, confirm that log-level has been changed in the active configuration.

Common Clash cores and mihomo support levels such as silent, error, warning, info, and debug. Start with info for everyday use. When troubleshooting, switch to debug, reproduce the issue once, then switch back. Detailed logs generate more output and may expose the domains you visit.

Change the setting in the configuration

  1. Back up the current configuration, then check whether your client supports persistent overrides, configuration merging, or local configuration editing.
  2. Set log-level: debug at the top level. If the field already exists, edit it rather than adding a duplicate.
  3. Apply the change using the client’s configuration reload feature. If the client asks you to restart the core, follow its instructions.
  4. Open the log panel and make sure it isn’t still showing only warning or error entries. Perform the failing action once and keep about 30 seconds of logs from before and after it.
  5. When you’re done collecting logs, restore log-level: info to avoid generating large volumes of access records over time.
# Top-level field snippet; merge into the existing configuration
log-level: debug

This is not a complete configuration. Direct edits to a file generated from a subscription may be overwritten during the next update. If your client supports overrides, use a persistent override instead. Menu locations vary between client versions, so don’t treat one client’s Settings path as the standard for every Clash client.

What to look for in a connection log

Check the time first, then the destination, rule, and error. Connection entries often include a [TCP] or [UDP] marker; terms like match and using usually indicate the matched rule and outbound. The exact output depends on the core, so don’t expect every entry to include every field.

Field or log entryWhat to check
Time and protocolDoes it match the failed action? Do TCP and UDP behave differently?
Source addressDid the request come from this device or the expected app, rather than a background update or another device on the local network?
Destination domain and portIs it the website’s port 443, DNS port 53, or the proxy server’s own service port?
Rule and policyDid traffic match DIRECT when you expected a proxy, or get blocked by REJECT? Which member did the policy group actually select?
End of the error chainWhat directly caused the connection to fail: DNS resolution, a timeout, a refused connection, or a protocol or certificate error?

DIRECT means the request used a direct outbound route; it doesn’t mean the request succeeded. REJECT means the policy blocked it, which may be the intended result. Even if the log shows a proxy group, check the connection details or policy page to confirm which node was actually selected. Automatic policy groups may select different members between tests.

How dial tcp, timeouts, and connection drops differ

dial tcp: check the address and error that follow

dial tcp 192.0.2.10:443: connect: connection refused
dial tcp 192.0.2.10:443: i/o timeout
dial tcp: lookup proxy.example on 127.0.0.1:53: no such host

dial tcp only indicates that a TCP connection is being established; it isn’t an error diagnosis by itself. The 192.0.2.10 address in this example is reserved for documentation. In a real log, determine whether the address belongs to the proxy server or the direct-connection destination. If the proxy server itself can’t be reached, changing the destination website’s routing rule usually won’t help.

  • connection refused: The connection was explicitly rejected. Common causes include no service listening on the port, an incorrect port, or a firewall actively rejecting the connection. This doesn’t mean the username or password is wrong; authentication usually happens after the connection is established.
  • i/o timeout: A network read or write operation didn’t complete before its deadline. Possible causes include packet loss, an unresponsive destination, egress restrictions, or a stalled protocol stage. Use the surrounding error messages to determine where it occurred.
  • network is unreachable: The device or current network has no usable route. Check the network interface, default route, and IPv6 connectivity first—not the authentication details.

context deadline exceeded: the operation timed out

This means an operation with a deadline didn’t finish in time. It can occur during a DNS request, health check, or connection attempt. These words alone don’t identify the node. Keep the surrounding context—for example, whether the entry came from the DNS or proxy dialer—and compare it with other connections from the same time.

EOF and connection reset by peer: the connection closed after it was established

EOF means the connection ended while data was being read; connection reset by peer means a reset was received. Possible causes include the server closing the connection, a protocol mismatch, or interference from an intermediary network device. If it happens every time during the handshake, check the node type, port, TLS settings, and transport parameters. If it appears only occasionally when an idle connection closes and access works normally, don’t diagnose a fault based on that entry alone.

DNS resolution failures: distinguish the node domain, destination domain, and resolver

If you see lookup, no such host, or DNS request failed, first note which domain was being resolved. If the node server’s domain can’t be resolved, all requests through that node may be affected. If only one destination domain fails, start by checking its DNS records and resolution path.

Log clueWhat it means and what to check next
no such hostNo usable result was returned. Common causes include a nonexistent domain or a negative response from an upstream resolver. Check the spelling, domain status, and resolver in use.
DNS request timed outFirst check that the DNS upstream is reachable and the protocol is configured correctly. With DoH, also consider how the DoH server’s domain is resolved initially.
Connection to 127.0.0.1:53 failedCheck that a DNS service is actually listening on port 53 on this device. The loopback address refers to the current device, not the router or another device.
server misbehavingThis often indicates a failure response from the DNS server. Check the specific response and compare it with other resolvers; don’t assume the domain doesn’t exist.

System lookup results may not reflect the client’s DNS path

For example, running nslookup example.com usually queries the resolver selected by the system. If the client uses built-in DNS, fake-ip, or a separate DNS upstream, that result may not match the resolution path used by the app. First check the active configuration’s listening address and port, and whether the app’s requests are being intercepted.

In fake-ip mode, an address in the 198.18.0.0/16 range may be a mapped address assigned by the configuration; that alone doesn’t indicate a DNS error. If an app still holds an old mapping and the mapping state changed after the core restarted, close the app’s connections and clear its cache using the client’s supported method, then test again.

mihomo’s proxy-server-nameserver can be used to resolve proxy node domains. Whether you need this field depends on the core version and your existing DNS setup. Don’t add a mihomo-specific field to an older core that doesn’t support it, and don’t replace the entire DNS configuration at once. First identify which domain and upstream are failing.

Where to start with port, TLS, and configuration errors

address already in use: the local listening port is occupied

If the startup log says it can’t listen on 127.0.0.1:7890, first check whether two clients are running or an old core process is still active. Port 7890 is only a common example; use the actual value configured for mixed-port, port, or socks-port.

# Windows PowerShell: check the process listening on the example port
Get-NetTCPConnection -LocalPort 7890 -State Listen |
  Select-Object LocalAddress, LocalPort, OwningProcess

# macOS: check TCP listeners on the example port
lsof -nP -iTCP:7890 -sTCP:LISTEN

# Linux: check TCP listeners on the example port
ss -ltnp 'sport = :7890'

After identifying the process, release the port by exiting the app normally or change the listening port. Don’t force-terminate an unknown process just because you found its PID. After changing the port, update the system proxy or app’s proxy address too; otherwise, the core may run normally while the app keeps connecting to the old port.

x509 and TLS handshake errors: check the time, certificate, and server name

For x509: certificate has expired or is not yet valid, first check the device’s date, time zone, and automatic time sync, then verify the server certificate’s validity period. If the certificate name doesn’t match, check the server address, TLS server name, and the provider’s configuration requirements. A TLS handshake timeout can also indicate network blocking or a port protocol mismatch; it doesn’t necessarily mean the certificate has expired.

Configuration loading failed: restore a working state first

For YAML parsing errors, unknown policies, or missing proxy groups, first undo the most recent change. YAML indentation uses spaces; avoid tabs. Policy names referenced by rules must match the names actually defined. If the core hasn’t loaded its configuration successfully, subsequent webpage failures aren’t simply a routing problem. Get the configuration to load and the ports to listen first, then troubleshoot connections.

Reproduce the issue in order: change one variable at a time

Logs can be swamped by background sync, automatic health checks, and app retries. A useful reproduction isn’t about collecting as much as possible; it’s about linking one action to a short slice of logs. The repeatable steps below use illustrative times.

  1. 14:20:00 — Record the baseline. Note the client, core, and operating system versions; network type; current mode; whether TUN is enabled; and the node selected in the policy group.
  2. 14:20:10 — Start a brief capture. Set core logging to debug, clear the old entries in the panel or note the start time, and preserve any original startup or configuration-loading errors.
  3. 14:20:20 — Visit one destination. Close unrelated tabs and open just one URL that previously failed. Note the browser error and the destination port, rule, and outbound shown in the log.
  4. 14:20:40 — Run one comparison. Keep the destination, mode, and network unchanged; switch only the node. If none of the node domains resolve, check DNS before switching randomly again.
  5. 14:21:00 — Summarize what changed. Was no traffic captured, did the wrong rule match, did the node connection fail, or did the destination respond unexpectedly after the connection was established? State the specific stage.

No logs? Check traffic interception instead of raising the log level

You can use a request through the local proxy as a comparison. The command below applies only if the current configuration provides an HTTP or mixed proxy at 127.0.0.1:7890. In Windows PowerShell, use curl.exe to avoid confusion with command aliases.

curl --proxy http://127.0.0.1:7890 --connect-timeout 10 --max-time 20 -I https://example.com/

Here, 10 seconds is the timeout for establishing the connection, and 20 seconds is the overall request limit—not a speed measurement. The command sends a HEAD request; some websites handle HEAD differently from a regular page request. It’s useful for checking an explicit proxy route, but it doesn’t replace a browser test or confirm that TUN has captured all traffic.

If the command produces connection logs but the browser doesn’t, check the browser’s proxy extension, system proxy, and app-specific settings. If the issue started after enabling TUN, note the route and DNS state, then compare with a single on/off change. Don’t change TUN, DNS mode, node, and rules all at once, or you won’t know which change mattered.

Share a troubleshooting report: keep context, remove sensitive details

When reporting an issue to a maintainer or service provider, include the relevant logs from about 30 seconds before and after the failure. That’s more useful than a screenshot showing only the last line. Text logs are easier to search and compare, but check them for credentials and personal information first.

  • Keep: The exact time and time zone, client and core versions, full error, destination port, matched rule, protocol used, and any single-variable tests already performed.
  • Remove: Full subscription URLs, authentication tokens, passwords, UUIDs, controller API secrets, and any access domains or device paths you don’t want to disclose.
  • Redact consistently: Use the same alias for a node across different logs so entries remain linkable. Don’t replace every domain and address with the same text.
  • Separate original logs from summaries: Label actual logs and reproduction steps clearly. Don’t present a rewritten example as raw client output.

State the conclusion as specifically as possible: “TCP connection to the proxy server timed out,” “the rule routed the destination to DIRECT,” or “the node domain failed to resolve”—not just “Clash doesn’t work.” Identify the failing stage first, then choose the relevant network, routing, or configuration checks. That gives you a clear basis for any changes.