First identify which component produced the log
Clash, Clash Meta, and mihomo logs can look similar, but one page may combine client logs, core logs, and configuration update records. Before troubleshooting, identify which component generated the error. The client downloads subscriptions, writes configuration, and starts the core; the core handles DNS, rule matching, proxy connections, and TUN traffic. Changing proxy rules will not fix a failed subscription download, and latency tests are meaningless when the core never started.
What to look for in each record type
- Client records: These commonly show subscription URL requests, configuration saves, core process launches, and system proxy changes. For HTTP 401, 403, 404, or configuration write errors, check the subscription and file permissions first.
- Core startup records: These show configuration loading, the DNS module, listening ports, rule providers, and TUN initialization. Errors here often stop the core or disable a specific feature.
- Connection records: These include TCP, UDP, source addresses, target domains, matched rules, and the final policy group. Check them first when a website will not open, an app bypasses the proxy, or a node times out.
Menu names vary slightly between clients. Usually, live logs are under “Settings” → “Logs” or “Core” → “Logs”; some desktop clients place them under “Home” → “Logs.” mihomo GUI clients often let you adjust the log level under “Settings” → “Preferences.” When reproducing a problem, keep the log view open, clear old records, and perform the failed action once. The resulting sample is much easier to read.
Understand levels, connection direction, and rule results
Common log levels include debug, info, warning, and error. info records normal connections and does not indicate a fault; warning indicates a failed operation, fallback, or temporary issue while the core usually keeps running; error deserves higher priority. For rule troubleshooting, temporarily use debug, then switch back to info to avoid continuously writing large amounts of DNS and connection detail.
[INFO] [TCP] 127.0.0.1:53142 --> example.com:443
match DomainSuffix(example.com) using Proxy[HK-01]
[WARNING] [TCP] dial Proxy (match DomainSuffix/example.com)
127.0.0.1:53142 --> example.com:443 error: i/o timeout
The first line shows the local process opening a TCP connection from temporary port 53142 to example.com:443. It then matches the DOMAIN-SUFFIX rule and passes the request to the Proxy policy group; HK-01 in brackets is the node actually selected by that group. The second section says the connection entered the proxy chain but did not complete within the deadline. You can therefore rule out “the rule did not match” and focus on the node, upstream network, or destination site.
Break down the log in this order
- Confirm whether the protocol is TCP or UDP. Most HTTPS web traffic uses TCP 443, but it may also use UDP 443 through QUIC.
- Confirm the source address.
127.0.0.1usually indicates a system proxy or local app; with TUN interception, it may show a virtual network adapter address. - Confirm whether the target is a domain or an IP address. When only an IP is available, some domain rules cannot participate in matching.
- Check the rule type and rule details after
match. - Check the policy group and actual node after
usingto see where the connection ultimately went. - Finally, read the
errorcontent and distinguish a timeout, refusal, resolution failure, or authentication failure.
dial tcp timeout: the connection was not established before the deadline
dial tcp means the core is establishing a TCP connection. Messages such as i/o timeout, connect: operation timed out, and context deadline exceeded all indicate that the wait exceeded its deadline, but the timeout may occur at different points. The failure could be connecting to the proxy server, or the proxy server could be failing to reach the destination. Use the node name, target address, and pattern of consecutive failures before the error to determine which.
Only one node times out
If HK-01 repeatedly times out in the same policy group while SG-02 opens the same website normally, the problem is likely limited to that node or its route. Run a latency test in the client, then verify with a real webpage. A test URL returning 200 only proves that the test path is reachable; it does not mean every destination is accessible. Three consecutive timeouts lasting over 5 seconds say more about instability than a single 800 ms result.
All nodes time out at once
- Check whether the current network can open ordinary websites outside the subscription service, ruling out a local connectivity failure.
- Make sure the system clock is accurate. A difference of several minutes can affect the TLS handshake and time-stamped authentication protocols.
- Check whether the node server address resolves. If the log also contains
lookuporDNS request failed, fix DNS first. - Temporarily disable any other VPN, proxy app, or network filtering tool to prevent overlapping routes.
- If TUN is enabled, switch to system proxy mode for a retest. If the system proxy works but TUN does not, focus on the virtual adapter, routes, and permissions.
[WARNING] dial tcp 203.0.113.20:443: i/o timeout
[WARNING] dial tcp: lookup node.example.net: i/o timeout
These two lines require different approaches. The first has already obtained the server IP, so the timeout occurred during the TCP connection stage; the second is still at the DNS resolution stage. Check the server port and network path for the former, and the DNS server, DNS route, and local network for the latter.
connection refused: the destination explicitly rejected the connection
connection refused differs from a timeout. A timeout means no valid response arrived in time; a refusal means the destination host quickly returned a rejection. Common causes include no service listening on the port, a stopped service, an incorrect port, or a local app connecting to a Clash listening port that is not running.
dial tcp 127.0.0.1:7890: connect: connection refused
dial tcp 198.51.100.8:8443: connect: connection refused
The target in the first line is 127.0.0.1:7890, meaning an app tried to connect to a local proxy port where no process is listening. Check the client core status and make sure the app's proxy address matches the Clash configuration. 7890 is a common mixed proxy port, but a user configuration may use 7897, 7899, or another value, so do not rely on the default.
The second line shows that a remote address refused the connection. If it belongs to a node server, verify the node port, protocol type, and subscription update time. A VMess port entered in a Trojan configuration, or an old subscription after the server changed ports, can be rejected immediately. Switching rule modes repeatedly will not help because the failure occurs while connecting to the proxy server.
DNS resolution failed: first identify who handled the request
DNS issues often appear as a browser message saying the server cannot be found, alongside lookup, no such host, all DNS requests failed, could not resolve, or an upstream DNS timeout. The key is to determine whether requests go through the operating system, Clash's DNS module, or the browser's own secure DNS. When all three run in parallel, changing one may not affect the request that actually matters.
Check the core DNS configuration
dns:
enable: true
listen: 0.0.0.0:1053
ipv6: false
enhanced-mode: fake-ip
nameserver:
- 223.5.5.5
fallback:
- tls://1.1.1.1:853
This configuration makes the core listen for DNS on port 1053; requests will not automatically appear on the system's port 53. GUI clients usually add the required routes when TUN or DNS interception is enabled. If you only copied the configuration without directing system DNS to the core, apps may still use the old resolver. Conversely, if another program already occupies the port, startup logs will show bind: address already in use.
Choose the troubleshooting path based on the symptom
- All domains fail, but direct IP access responds: Check the DNS listener, upstream DNS, and firewall first.
- Mainland China domains work, but specific domains fail: Check whether nameserver-policy, fallback, or rule providers are sending DNS requests over an unreachable route.
- The browser fails while other apps work: Check the browser's secure DNS settings and proxy extensions to confirm whether it is bypassing system DNS.
- A Fake-IP address appears but the connection fails: A reserved address returned by Fake-IP is normal. Continue by checking domain restoration, rule matching, and the proxy connection instead of treating the reserved address as the real server.
- Failures begin only after TUN is enabled: Check DNS hijacking, the default route, and virtual adapter permissions to prevent DNS requests from being sent back to the core in a loop.
After changing DNS, clear the old cache before testing. On Windows, reconnect to the network or run ipconfig /flushdns in a terminal; on macOS, disable and re-enable the network interface. Browsers may also retain their own DNS and connection caches, so fully quit the browser before retesting for more reliable results.
Rule not matched: the log may contain no error
Incorrect rule routing often produces no red error. The connection succeeds, but uses DIRECT, the wrong node, or the final MATCH, so it still feels as if the rules are broken. Clash and mihomo evaluate rules from top to bottom in configuration order and stop at the first match. A broad rule placed first can mask a more precise rule below it.
rules:
- DOMAIN-SUFFIX,example.com,DIRECT
- DOMAIN,api.example.com,Proxy
- MATCH,Proxy
When visiting api.example.com, the first DOMAIN-SUFFIX rule has already matched, so the second exact-domain rule is never evaluated. If the API should use the proxy, move DOMAIN,api.example.com,Proxy higher in the list. If the log shows match DomainSuffix(example.com) using DIRECT, the rule system is working; the issue is rule order, not the core ignoring the configuration.
How to investigate when the log shows only an IP
When the target appears as an IP such as 142.250.0.1:443, DOMAIN and DOMAIN-SUFFIX rules may have no domain to match. Possible causes include the app connecting directly to an IP, DNS mapping not being associated with the connection, or traffic not passing fully through the core. Check whether IP-CIDR, GEOIP, or the final MATCH was hit. An IP rule using no-resolve does not perform an extra domain lookup for matching; it does not “skip this rule.”
Rule provider failed to load
When a remote rule provider cannot be downloaded, logs may show HTTP 404, context deadline exceeded, or provider update failed. Check the provider URL and update time first, then confirm which policy handles the download request. A first-load failure may make dependent rules unavailable; if a cache exists, the core may continue using the previous version. Note whether the failure occurs during startup or a scheduled update.
Subscription, configuration, and core startup errors
If the log contains no TCP or UDP connection records at all, first confirm that the core loaded the configuration successfully. YAML indentation errors, policy groups referring to missing nodes, port conflicts, and unsupported configuration fields can all make the core exit before it takes over traffic.
Subscription issues by HTTP status code
| Log status | Common meaning | Check first |
|---|---|---|
| 401 Unauthorized | The request lacks valid authentication credentials | Whether the subscription token is complete and the link was truncated |
| 403 Forbidden | The server received the request but refused to provide the content | Subscription status, access restrictions, and request origin |
| 404 Not Found | The subscription path does not exist | Whether the link has expired or the path was copied incorrectly |
| 429 Too Many Requests | Too many requests in a short period | Pause automatic refresh and wait for the limit to clear |
| 5xx | The subscription service is temporarily unavailable | Try again later and keep the current working configuration |
YAML and reference errors
yaml: line 42: did not find expected key
proxy group Proxy: proxy HK-01 not found
listen tcp 127.0.0.1:7890: bind: address already in use
did not find expected keyusually points to incorrect indentation, a missing colon, or an unclosed quote. YAML should use spaces for indentation; do not mix in tabs.proxy not foundmeans a policy group refers to a node or child policy group that does not exist. Check spaces, capitalization, and whether a subscription update renamed the node.address already in usemeans the listening address or port is already occupied. Quit the old core process, or change the mixed-port under “Settings” → “Preferences” and restart.- When
permission deniedappears during TUN initialization, it usually relates to virtual adapter permissions or system service status. If system proxy mode works, keep using it temporarily and troubleshoot TUN separately.
Clash Premium, Clash Meta, and mihomo do not support exactly the same configuration fields. A configuration generated by a newer mihomo core may produce an unknown field error or fail to parse when loaded by an older core. First confirm the actual core name and version under the client's “About” or “Core” page, then compare the fields supported by that core rather than checking only the client shell version.
A reproducible log troubleshooting workflow
- Record the symptoms: Note the failure time, app name, target domain, and whether system proxy or TUN is enabled.
- Confirm core status: Check that the core is running, mixed-port is listening, and startup logs contain no configuration errors.
- Clear the logs: Set the level to info and remove historical records so old errors do not distort the diagnosis.
- Reproduce it once: Open one failing page, refresh the subscription once, or perform one node connection test. Do not operate multiple apps at the same time.
- Find the target first: Search for the domain, IP, or subscription address, then inspect 10 to 20 lines of context before and after it.
- Identify the stage: Subscription HTTP errors belong to the subscription stage; YAML and port errors belong to startup; lookup belongs to DNS; match belongs to rules; dial belongs to connections.
- Change one variable at a time: Change only one node, one DNS upstream, or one interception mode per test. Clear the logs again after every change.
- Restore the log level: After resolving the issue, switch from debug back to info to reduce unrelated records.
For example, a website fails after 8 seconds in TUN mode but opens within 1.2 seconds in system proxy mode. The logs show the same node matching the rules; system proxy mode completes the TCP connection, while TUN mode has no corresponding target record. The node and rules can therefore largely be ruled out. Focus instead on TUN routing, whether the app uses the virtual adapter, DNS hijacking, and system permissions. This comparison is more effective than switching through ten nodes in succession.
Before sharing logs, you can retain timestamps, error types, target ports, rule types, and policy group names while redacting subscription tokens, authentication fields, full node addresses, and your local username. Do not share only the final error line; keep at least the startup information or connection context before and after it, or it will be difficult to tell whether the timeout occurred at DNS, the node, or the destination site.