First, tell a failed download from a parse error
A subscription import usually involves four steps: requesting the URL, receiving a response, parsing the configuration, and loading it. An “update failed” message could refer to any of them. Identify the failing step before deciding whether to refresh the link, change the request method, or check the configuration structure.
Keep your current working configuration, then manually update the failed subscription once. Open the client’s log and note the time of the attempt, the HTTP status code, and the first error. Menu names vary across clients; look for subscription update logs, not connection test results.
| Log clue | Stage | Check first |
|---|---|---|
no such host |
DNS resolution | Check that the subscription domain is correct and DNS is working |
timeout or connection refused |
Connecting or reading the response | Network route, proxy port, and server availability |
| HTTP 401、403、404、410 | Server response | Authorization, access restrictions, and whether the link has been replaced |
yaml: and a line number |
Parsing the response | Check whether the response is a configuration and whether its indentation and data types are valid |
proxy not found |
Configuration references | Check that policy groups, nodes, and rule targets use matching names |
Expired links and account status
Copy the full subscription URL again
Copy the Mihomo subscription URL from your provider’s account page. Don’t use the account login or purchase page, or a console URL from your browser’s address bar. Check for extra spaces, line breaks, or non-ASCII punctuation, and make sure chat apps haven’t truncated any parameters after ?.
- 401: Usually indicates missing or invalid authentication. Check the link token and account status first.
- 403: May indicate denied authorization, or restrictions based on request headers, region, IP, or risk controls. The status code alone doesn’t prove that the subscription has expired.
- 404 or 410: The endpoint may have moved, the link may have been revoked, or the resource removed. Check your account page.
- 429: Too many requests. Wait as directed by
Retry-Afterand avoid repeatedly clicking Update. - 5xx: Check the server status first and try again later. Avoid making major changes to your local configuration prematurely.
Exhausted data, an expired plan, and an invalid token are different issues. Some services return an empty list or an explanatory message instead of a clear 401. Check both the response body and your account status; a “successful” request alone isn’t enough.
What browser checks can—and can’t—tell you
Opening a subscription URL directly on a trusted device can help identify a login page, error page, or file download. But a browser may send login cookies and use a different User-Agent from the client. A successful browser download doesn’t guarantee that the client will receive the same content, and garbled text in the browser doesn’t necessarily mean the configuration is corrupted.
If the URL returns a login form or CAPTCHA, first confirm that you copied the dedicated subscription URL. Don’t save the webpage as a .yaml file and import it. Browser tests leave a history entry, so take extra care on shared devices.
Check the HTTP response and its actual contents
A file extension doesn’t tell you what’s inside. A response named config.yaml might contain HTML, and an HTTP 200 response might display a “subscription expired” message. Check the status code, redirects, and the start of the response body.
Use curl to capture results for comparison
These commands are for macOS or a Linux Bash terminal with curl installed. Input is hidden as you type and the URL isn’t written directly to shell history. However, while the request runs, the expanded URL may be visible to local processes with sufficient permissions. Output files may also contain credentials, so keep them local.
read -r -s -p 'Subscription URL: ' SUB_URL
printf '\n'
curl --location --max-redirs 5 \
--connect-timeout 10 --max-time 30 \
--dump-header subscription-headers.txt \
--output subscription-response.txt \
--write-out 'HTTP %{http_code}\n' \
"$SUB_URL"
unset SUB_URL
The connection timeout is set to 10 seconds, the overall request limit to 30 seconds, and redirects are limited to 5. These are troubleshooting settings, not measured service performance. Don’t add -k to skip certificate verification or use --location-trusted, which can expose credentials to redirect targets.
- Check curl’s errors in the terminal and the final HTTP status. If no HTTP response was received, the status may show as
000; this is not a server status code. - Check
subscription-headers.txt. If redirects occurred, the file may contain multiple sets of response headers; inspect the last one. - Open
subscription-response.txtin a local text editor. Check whether it starts with configuration fields, an encoded node list, or HTML and an error message. - Check that the redirect target is a domain approved by your provider. Don’t share response headers publicly; they may contain cookies or token-bearing URLs.
Content-Type is a clue, not definitive proof. Some services label YAML as text/plain, and it may still work. Conversely, a YAML content type doesn’t guarantee that the body has valid syntax or structure.
Tell full configurations, node lists, and encoded subscriptions apart
Confirming that “the response is YAML” is only half the check. A full Mihomo configuration, a node list used by proxy-providers, and a URI or Base64-encoded node subscription are different input formats. Whether a client can convert them depends on its implementation; don’t assume every client supports automatic conversion.
| What it contains | Typical use | Common misuse |
|---|---|---|
| Proxy sources, policy groups, and rules | Load as a complete configuration | References to missing nodes or policy groups |
A node list built around proxies: |
Referenced by proxy-providers |
Assuming it includes all policies and routing rules |
Multiple ss://, vmess://, or similar links, or encoded text containing them |
Import and convert with a tool that supports the format | Load directly as the core’s YAML configuration |
<!DOCTYPE html> or <html> |
A webpage or access-block response | Trying to fix it by changing the file extension to YAML |
YAML line numbers and field types
If the log points to line 18, the problem may not be on line 18 itself. A missing colon or unclosed quote on the previous line can cause the parser to fail on the next one. Check at least three lines before and after the reported line. Use spaces for indentation and avoid tabs.
# Structure example only; not a complete, network-ready configuration
proxies: []
proxy-groups:
- name: Manual Selection
type: select
proxies:
- DIRECT
rules:
- MATCH,Manual Selection
This example shows list and indentation structure; it contains no proxy nodes. In a real configuration, rule targets, policy group names, and node names must match exactly. Chinese punctuation, trailing spaces, and differences in capitalization can all cause references to fail.
YAML syntax validity doesn’t guarantee core support
Valid YAML doesn’t mean your current core supports every protocol, transport, or field it contains. First, note the actual core version on the client’s About page or core information screen, then check what that version supports. The client version and core version are not the same thing.
For further troubleshooting, save the full configuration in a restricted directory and test it with your local Mihomo installation using mihomo -t -f config.yaml. This doesn’t test network availability; if the configuration uses external resources, check the resource loading logs too. Don’t enable a service with an unreviewed configuration.
User-Agent and subscription response formats
Some subscription services use the User-Agent to decide which configuration to return. If the same URL returns an information page in a browser and YAML in a client—or the other way around—the User-Agent may be the reason. Prefer the Mihomo subscription URL specified by your provider instead of changing request headers at random.
- Keep the URL, network, and approximate test time the same. Change only the User-Agent to avoid changing multiple variables at once.
- First note the request details available in the client logs, then check your provider’s documentation for the required User-Agent value.
- Use curl’s
--user-agentoption to compare results. Save each response separately and compare the status codes and body structure. - Once you’ve confirmed the result, check whether the client lets you set this header specifically for subscription requests. Changing browser settings alone won’t help.
For example, if your provider explicitly supports this identifier, you can test --user-agent 'clash.meta'. This isn’t a universal fix for subscription services, nor does it guarantee a configuration compatible with your current core. If the response is still a login page or 403, check authorization and network restrictions instead of cycling through more identifiers.
Network, DNS, and proxy routing for updates
The browser connects, but the client times out
First, check whether both requests use the same network route. The browser may use the system proxy, while the subscription updater may connect directly, use a built-in proxy, or follow a separately configured download route. Enabling the system proxy doesn’t mean every process will use it automatically.
If the client has an option such as “Update subscriptions through proxy,” first make sure the existing proxy works. If the subscription has expired and no nodes can connect, forcing an update through an old node can create a dependency loop. Keep a working configuration and try another network route using an option supported by your provider.
- DNS: For
no such host, check the domain spelling and system DNS resolution. Don’t hard-code a service IP that may change. - Proxy port: If your local HTTP proxy is set to
127.0.0.1:7890, confirm that the client is actually listening on that port. 7890 is an example, not a default for every client. - TUN: TUN can change how a process’s traffic is routed, but it can’t fix invalid YAML. Note the current setting before switching it, then restore it after testing so you don’t conflate two different issues.
- TLS: For certificate errors, check the system date and time zone, subscription domain, and any network sign-in page. Don’t disable certificate verification.
Compare the results on a different network
If possible, make one request over your usual network and another using a phone hotspot. Keep the URL and User-Agent unchanged. If only one network returns an HTML block page or times out, focus on the network route. If both consistently return the same format error, look at the subscription contents and client compatibility instead.
curl’s --noproxy '*' option bypasses explicit proxies configured at the curl level, but not system TUN, routing rules, or network egress devices. So if the request still fails with this option, that alone doesn’t prove the direct network path is the problem.
Restore the import and share only essential details
After making changes, manually update once to confirm the configuration parses, then switch to it and test the connection. A successful subscription update means the content was received and processed; it doesn’t mean every node works or that DNS, the system proxy, and routing rules are fully configured.
- Check the subscription update time, node count, and whether the expected policy groups are present.
- Review the loading logs for errors such as unsupported node types, failed provider downloads, or missing rule targets.
- Connect to a known reachable test destination and check the connection logs for the matching rule, policy group, and outbound route.
- Keep the old configuration available for recovery. Once the new one is stable, remove any temporary response files.
What to include if the problem persists
When contacting the client maintainer or subscription provider, include your operating system, client and core versions, time of failure, HTTP status code, first error with sensitive details redacted, and a comparison of direct and proxied updates. For format issues, share a minimal snippet that preserves indentation. Don’t send the full subscription URL or node credentials.
Work through the checks in this order: confirm the URL and authorization, inspect the response body, verify the format and core support, then compare request headers and network routes. Change only one variable at a time. This helps avoid misleading “it worked once” results and makes the issue easier to reproduce and fix on future subscription updates.