How to Read Clash Logs: Common Errors and Troubleshooting Steps

Learn how to read log levels and fields, diagnose timeouts, DNS failures, port conflicts, and unmatched rules, and follow a practical troubleshooting sequence.

Reproduce the issue once, then filter the relevant logs

If a page won’t load in Clash, the node isn’t necessarily at fault. The request may never reach the core, or it may get stuck during DNS resolution, rule selection, the proxy handshake, or the destination server’s response. The key is to identify the last step that succeeded—not to replace your entire configuration as soon as you see a red error.

This guide covers common logs from the original Clash and Clash Meta (now called mihomo). Log fields and display formats vary across cores, versions, and clients, so the examples explain the general structure rather than guaranteed wording. Before comparing logs, note the client version and the core name and version from the client’s About page or core information screen. The client version is not a substitute for the core version.

  1. Keep a copy of your current configuration and note your system proxy, TUN status, operating mode, and selected policy group.
  2. Open the client’s Logs page. Menu names vary by client; if you can’t find it, check that client’s documentation first.
  3. Pause other downloads, note the current time, and visit just one URL that reliably reproduces the issue.
  4. Keep about 10 seconds of logs from before and after the request. Filter by destination domain, destination port, or source connection port.

Log levels and fields: check the matched rule, then where the request failed

The log-level setting controls how much detail is logged. Keep it at info for everyday use; temporarily switch to debug when reproducing a hard-to-diagnose issue. Apply the change, then restore the usual level when you’re done so debug output doesn’t bury important errors.

log-level: info
SettingPurposeWhat to look for
debugTemporarily show more detail about internal processingFilter by time and destination instead of guessing from individual lines
infoSee routine connections and policy selectionThe matched rule, actual outbound, and destination address
warningKeep warnings and more severe messagesWhether connection failures keep affecting the same destination
errorReduce routine messagesNot suitable for determining on its own whether traffic reached the core
silentDisable routine log outputSwitch back to a visible log level before troubleshooting

The configured value is warning, though the interface may display it as WARN; don’t mistake a display abbreviation for the configuration value. Log level also doesn’t indicate how serious an issue is: a warning may come from a page’s statistics request, while a connection using the wrong policy can still appear as a routine info message.

time="2026-08-06T10:20:30+08:00" level=info msg="[TCP] 127.0.0.1:53124 --> www.example.com:443 match DomainSuffix(example.com) using Manual Select[Node-A]"
  • time: The event timestamp. Check the time zone and system clock before comparing logs from different devices.
  • [TCP]: The connection protocol. Check UDP requests separately; a TCP test alone isn’t enough.
  • 127.0.0.1:53124: The source address and ephemeral port, not the proxy listening port.
  • www.example.com:443: The destination host and port. HTTPS usually uses 443, but not every application uses the default port.
  • match: The rule matched by this request. The text after using typically shows the policy group and the selected outbound.

using in a log means an outbound was selected; it doesn’t mean the connection succeeded, let alone that the page fully loaded. Check for a dial failure, handshake error, or closed connection for the same destination around the same time.

Connection timeouts: distinguish the proxy server from the destination server

i/o timeout, context deadline exceeded, and dial errors containing timeout all mean a step took longer than its allotted wait time. The word “timeout” alone doesn’t tell you whether the problem is your local network, the node’s route, or the destination site.

Use the address in the error to find where the connection stalled

  1. Timed out connecting to the proxy server: Check whether the error points to the server address and port in the node configuration. If so, start by checking whether the node is reachable, your local network, and the server port.
  2. Timed out connecting directly to the destination: If the log shows DIRECT and the error points to the destination IP on port 443, first confirm that the rule is supposed to connect directly.
  3. Handshake or remote read timeout: The TCP connection may have been established, but the subsequent protocol exchange didn’t finish. Check the node protocol, TLS settings, and server status.

Testing the same URL gives you a more useful comparison than opening several different sites. These commands assume an HTTP mixed port is configured on 7890. On Windows PowerShell, call curl.exe explicitly; on macOS and Linux, use curl.

curl -I --connect-timeout 5 --max-time 15 --proxy http://127.0.0.1:7890 https://example.com/
curl -I --connect-timeout 5 --max-time 15 --noproxy "*" https://example.com/

The first command explicitly uses the local proxy port; the second bypasses curl’s proxy settings. If TUN is still routing traffic, the second request may still pass through the core. To use it as a true direct-connection comparison, temporarily disable TUN under controlled conditions. A 403 or 405 is still an HTTP response, not simply a network connection failure.

DNS resolution failures: first find out what is doing the resolving

no such host means the lookup didn’t return a usable result, but it doesn’t necessarily mean the DNS server is down. A nonexistent domain, a negative response from an upstream server, or a problem with the local resolution path can all produce similar errors. Pay close attention to the domain after lookup: if it’s the proxy server’s domain, the failure happened before the node connection; if it’s the destination site, check the outbound and DNS configuration as well.

Test the core’s DNS on an explicit port

If the active configuration includes the DNS settings shown below, you can query the core on its listening port, 1053. The upstream address is for troubleshooting only; choose one that’s reachable on your network. Don’t replace the entire DNS section in your subscription configuration.

dns:
  enable: true
  listen: 127.0.0.1:1053
  enhanced-mode: fake-ip
  nameserver:
    - 1.1.1.1
# macOS / Linux (requires dig)
dig @127.0.0.1 -p 1053 example.com A

# Windows: enter these commands in nslookup's interactive mode, one at a time
nslookup
server 127.0.0.1
set port=1053
example.com
exit
  • Query times out: Confirm that the core loaded this configuration and is listening on port 1053, then check whether the upstream DNS server is reachable.
  • Returns NXDOMAIN: Check the spelling and compare with a domain you know exists. A nonexistent domain isn’t a network failure.
  • Returns a Fake-IP: For example, an address mapped within 198.18.0.0/16 when the configuration uses the default range is not, by itself, a resolution failure.
  • System lookup works, core lookup fails: Focus on the core’s DNS upstream and routing. If the reverse is true, check whether system DNS is actually using the intended path.

A plain nslookup example.com usually queries the DNS server configured for your system; it doesn’t confirm that the core’s DNS is working. With DoH or DoT, also consider bootstrap resolution for the upstream hostname, TLS verification, and the connection path. Not all mihomo DNS extensions are supported by the original Clash, so check your core’s supported features before adding them. See the DNS configuration reference for field details.

Port conflicts and connection refused errors: check whether the core is actually listening

bind: address already in use usually occurs during startup or reload. It means the process can’t bind to a local address and port, often because two clients are running at once or an old core process hasn’t exited. First identify whether the error concerns a proxy port, DNS port, or controller port—don’t change every port at once.

mixed-port: 7890
external-controller: 127.0.0.1:9090

In the configuration above, 7890 is the mixed proxy inbound port and 9090 is the controller port. The controller isn’t an HTTP proxy endpoint, so pointing your browser proxy at 9090 won’t work as expected. The commands below only inspect processes; they don’t terminate anything:

# Windows
netstat -ano | findstr :7890

# macOS
lsof -nP -iTCP:7890 -sTCP:LISTEN

# Linux
ss -lntp 'sport = :7890'
  1. Check which PID and application are using the port, then exit any duplicate client normally.
  2. If you switch to 7891, update the system proxy, browser extension, and command-line proxy settings as well.
  3. Restart the core, confirm there are no bind errors, then run the curl test again with the specified proxy port.

connection refused is different from a port conflict: it means the connection was rejected, often because nothing is listening on the destination port. If the refused address is 127.0.0.1:7890, check the local core first. If it’s the node server’s address, check the server port and service status. Don’t expose the listening address on every network interface just to fix a local access issue.

Rules not matching: check the mode, rule order, and final outbound

In Clash rule mode, rules in rules are checked from top to bottom, and the first match determines the policy. Having a correct rule in the list doesn’t mean it will ever be reached. Global mode doesn’t select outbounds by evaluating the same rule list, so confirm the current operating mode before troubleshooting.

mode: rule
rules:
  - DOMAIN-SUFFIX,example.com,DIRECT
  - MATCH,Manual Select

This snippet assumes the configuration already defines a policy group named “Manual Select.” Requests to www.example.com should match the first rule; other unmatched requests go to the final MATCH rule. If you put MATCH first, no later rules will be checked.

Check these four things

  • Check the configuration that’s actually loaded: The subscription source file, your locally edited file, and the client’s active configuration may differ. Confirm your changes were applied, not just saved in an editor.
  • Check whether the domain is available: If an app connects directly to an IP address and the core can’t recover the domain, DOMAIN-SUFFIX may not match. Sniffing can help, but it can’t recover the domain for every connection.
  • Check rule-set status: If you use RULE-SET, first confirm the provider downloaded and parsed successfully, then check the referenced name and rule order.
  • Check the policy group’s actual selection: The log may show the right group name, but if the selected member is DIRECT or a different node, the result won’t match your expectations.

Create a new connection when testing rule changes. Existing long-lived connections may keep using the original outbound, and refreshing a page may not recreate every connection. Close and reopen the test app, or close the relevant connections once you understand the impact. See the complete configuration reference for all fields and the subscription guide for update instructions.

TLS, authentication, and TUN errors: don’t treat them as the same network problem

Log clueCheck firstAvoid doing this without evidence
x509: certificate has expiredSystem clock and server certificate validitySkipping certificate verification outright
certificate is valid forConnection hostname, certificate name, and node TLS settingsChanging only the local proxy port
authentication failedWhich protocol reported the error, account credentials, and subscription statusChanging DNS over and over
permission deniedResource path, permissions, and service status shown in the full errorDeleting configuration without checking the context

First determine whether a TLS error occurred during the node handshake or the destination site’s handshake. When a node uses TLS, the server address, SNI, and certificate name must match the server configuration. A significantly incorrect system clock can also cause verification to fail. Disabling certificate verification changes your security protections and shouldn’t be used as a general fix.

TUN errors often occur while creating a virtual interface, setting routes, or taking over DNS. On Windows, check the client’s service mode and required permissions. On Linux, check whether /dev/net/tun exists and whether the process has the required permissions. On macOS, check the system permissions required by the client. Setting names vary between clients, so don’t follow menu instructions written for a different client.

If curl works with an explicitly specified proxy port but an app still fails with TUN enabled, focus on routing, DNS takeover, and conflicts with other VPNs or security software instead of continuing to switch nodes. See the TUN configuration reference for further setup. TUN taking over traffic doesn’t mean all traffic goes through the proxy; the operating mode and rules still determine the route.

Final check: verify the fix with the same request

After making a change, test the original URL again. Check both the app’s result and the path shown in the logs: did the page finish loading, did the expected rule match, was the expected node used, and did the same error stop recurring? A latency test that reports a number of milliseconds doesn’t prove that DNS, the destination site, and the app’s protocol are all working.

  1. Core didn’t start: Fix configuration syntax, port, and permission issues first.
  2. No request in the logs: Reproduce the issue at info level and check the system proxy, the app’s own proxy settings, and which traffic TUN is handling.
  3. Resolution error: Distinguish the node domain from the destination domain, then test system DNS and core DNS separately.
  4. Connection error: Use the address in the error to distinguish the local entry point, proxy server, and destination server.
  5. Connection succeeds but takes the wrong route: Check the operating mode, rule order, policy group selection, and existing connections.
  6. Issue resolved: Restore your usual log level and keep a record of the change that worked and the steps to reproduce the issue.

A useful troubleshooting record should answer three questions: which request, which rule it followed, and where it failed. Narrowing things down in that order is usually more effective than replacing large parts of the configuration—and makes it easier to retest after a subscription update or client upgrade.

Download client