Configuration Practices · Clash Technical Blog

Fixing invalid domain in Mihomo v1.19.30

Fix Mihomo v1.19.30 invalid domain errors in fake-ip-filter or skip-domain by replacing bad asterisks with valid wildcards or hostnames, then validate and keep a rollback.

  • Mihomo
  • YAML
  • Configuration validation
  • Configuration compatibility
On this page

First confirm that domain-pattern validation is failing

This article addresses one specific symptom: the same configuration starts on Mihomo v1.19.29 or earlier, but after upgrading to v1.19.30 the core reports Parse config error: invalid domain and exits during configuration loading.

Official issue #3116 recorded the change in a Linux Docker environment and traced it to domain patterns in sniffer.skip-domain and dns.fake-ip-filter. v1.19.30 includes stricter validation of Clash-style domain wildcards. This is not a failed node and cannot be bypassed by switching the proxy mode to Direct.

If the log says Invalid YAML, unsupported field, or proxy not found, or if the core starts but websites will not load, the failure occurs at another stage. Troubleshoot that error directly instead of changing every configuration failure to the wildcard syntax in this article.

Branch from the first error

Log or symptomMore likely stageDoes this article apply?
Parse config error: invalid domainDomain-pattern validationApplies when it appears after upgrading to v1.19.30
Invalid YAML or indentation errorYAML structureDoes not apply; fix the syntax first
proxy / group not foundPolicy-group or rule referenceDoes not apply; restore the missing reference first
The core starts, but only one domain failsDNS, rules, or networkDoes not apply; inspect connection records first

Save the working configuration and its generation source first

Before searching for asterisks, separately save the current final configuration, the client's Profile, Merge or override, and the subscription-conversion template. Backing up only config.yaml in the runtime directory is not enough: the invalid source pattern will overwrite the fix the next time the client updates the subscription.

If the old core is still forwarding traffic, do not restart the service or refresh the subscription repeatedly. Preserve the working state first, then copy the error log, client version, and actual Mihomo version. Remove the subscription token, node passwords, controller secret, and private domains from screenshots and configuration copies.

Prepare a rollback path

  1. Record the actual core version

    Confirm on the client's About page, in the startup log, or with mihomo -v that v1.19.30 is running; do not substitute “latest” for the version number.

  2. Export the final configuration

    Save the YAML actually loaded by the core, plus the Profile, Merge, override, or conversion template.

  3. Keep the previous core release

    Keep only the v1.19.29 file from the official Release that has already been verified on this machine as a temporary fallback.

  4. Hold other variables constant

    Do not change the subscription, node, DNS mode, or TUN setting at the same time during troubleshooting; avoid introducing a second failure.

Locate the first invalid domain pattern

Test the final configuration first with the v1.19.30 build you intend to run. The command used in the official issue is mihomo -t -f. A successful test only means the current core can parse and initialize the configuration; it does not start the proxy or prove that nodes work.

The stable v1.19.30 release may report only the generic invalid domain error. Search the final YAML and any referenced local files for asterisks, starting with sniffer.skip-domain and dns.fake-ip-filter, which the issue confirmed as problematic. Retest after each correction so the core can point to the next error.

Test the final configuration with the current v1.19.30
mihomo -v
mihomo -t -f /path/to/config.yaml
Read-only search for asterisks in domain lists on Linux / macOS
grep -R -n '\*' /path/to/config.yaml /path/to/rules 2>/dev/null

rrn-sw-*, a*.example.com, or *a.example.com

The asterisk is mixed into the same label, a pattern that v1.19.30 explicitly rejects.

*.example.com or time.*.com

The asterisk occupies an entire label, so the form itself is valid; continue to the next item.

example.com., a..example.com, or leading or trailing spaces

Strict validation also rejects a trailing dot, an empty label, and leading or trailing whitespace.

No asterisk can be found

Check for plus signs, trailing dots, empty labels, and the final configuration generated by the client; do not search only the original subscription.

Distinguish the three valid domain wildcard forms

Mihomo documentation calls this Clash-style domain wildcard syntax and explicitly notes that it differs from DOMAIN-WILDCARD in routing rules. Do not copy a seemingly similar asterisk expression from a routing tutorial directly into fake-ip-filter or skip-domain.

The key is not whether the asterisk comes first or last; it must occupy an entire dot-delimited label. time.*.com is valid because the middle label contains only the asterisk. rrn-sw-* is invalid because the asterisk and rrn-sw- share the same label.

Choose syntax based on the intended match scope

Valid syntaxMatch scopeDoes not match
*.example.comExactly one subdomain level, such as a.example.comexample.com、b.a.example.com
+.example.comThe root domain and subdomains at any depthOther suffixes
.example.comSubdomains at any depthThe example.com root domain
time.*.comExactly one complete label in the middletime.com、time.a.b.com
*A single-label hostname with no dotA fully qualified domain name containing dots
Invalid syntax examples: v1.19.30 rejects these partial-label wildcards
rrn-sw-*
a*.example.com
*a.example.com
a*b.example.com

Rewrite the pattern according to its real intent; do not make a mechanical replacement

If the intent is to match one or more subdomain levels under a fixed root domain, choose among the asterisk, plus sign, and dot-prefix forms. If the original intent is to match a group of LAN hosts beginning with rrn-sw-, Clash-style domain lists have no partial-label wildcard equivalent to rrn-sw-*; explicitly list the real hostnames instead.

Do not mechanically change rrn-sw-* to *.rrn-sw, rrn-sw.*, or +.rrn-sw. They describe different label structures and may pass validation without matching the intended hosts. List the actual queried names first, then make every configuration entry explainable in terms of its coverage.

Example: list LAN hosts explicitly while keeping a valid domain scope
sniffer:
  skip-domain:
    - "rrn-sw-01"
    - "rrn-sw-02"

dns:
  fake-ip-filter:
    - "+.example.com"
    - "time.*.com"

Invalid patterns and actionable remedies

Original intentDo not change it this wayActionable remedy
Match short hostnames beginning with rrn-sw-Keep using rrn-sw-*List the actual hostnames, such as rrn-sw-01 and rrn-sw-02
Match one subdomain level under example.coma*.example.comUse *.example.com
Match the root domain and all subdomains*example.comUse +.example.com
Match all subdomains but not the root domainUse *.example.com and assume it includes multiple levelsUse .example.com

Validate the fix with the same v1.19.30

After saving a candidate copy, test it with the same v1.19.30 build. If invalid domain remains, address the next error; do not overwrite the only working configuration just because the first error disappeared. Let the client load the candidate and restart the core only after every error is cleared.

A running core is only the first acceptance check. Visit a domain that should match fake-ip-filter, one that sniffer should skip, and an ordinary public domain, then inspect the DNS results and connection records. A syntax-valid pattern with the wrong scope is still not a completed fix.

Promote the candidate in rollback-safe order

  1. Test the candidate copy

    Run mihomo -t -f until v1.19.30 explicitly reports that the configuration test passed.

  2. Save the original before replacing it

    Keep the previous working YAML; do not overwrite the only original while the client is running.

  3. Reload or restart the core

    Confirm that the log shows v1.19.30 has started and is not still reading an old process or configuration.

  4. Retest real matching behavior

    Use known domain requests to check DNS, sniffing, rule matches, and final page access.

Completion criteria

  • The final configuration passes v1.19.30 test mode
  • The core starts and remains running with no new configuration parsing errors
  • The listed LAN hosts bypass sniffing or Fake-IP as intended
  • One-level, any-depth, and root-domain matching scopes agree with the selected syntax
  • Ordinary public domains and node connections are not harmed by the broadened rules
  • The original configuration, generation source, and old-core fallback file remain available

Fix the generation source if the error returns after an update

If manual changes allow the core to start but refreshing the subscription, switching Profile, or restarting the client brings the same error back, the invalid pattern comes from a conversion template, remote configuration, Merge, or override. Stop editing the temporary runtime file repeatedly. Compare the final YAML before and after the fix to find the layer that restores the old value.

If you control the subscription or converter, fix the template and regenerate it. If you control only the client, replace the complete list in a managed Merge or override, then confirm that the final configuration remains valid after an update. Do not upload a subscription containing a token to an unfamiliar converter site, and do not use one overly broad suffix to cover every unknown case.

The error returns after every subscription update

Revise the subscription conversion template or upstream configuration, then generate a new candidate.

The error returns after switching Profile

Check the Merge, Script, and local overrides for each Profile separately.

The file on disk is changed, but the core still reports the old value

Confirm the path actually loaded, the running process, and the final configuration generated by the client.

The configuration starts only with a broad suffix

List the required hosts and record any gaps first; do not treat expanded scope as a long-term solution.

Roll back safely first if an immediate fix is not possible

If an uncontrollable source keeps generating the configuration and cannot be corrected promptly, disable TUN or the system proxy to restore direct system connectivity, then restore the backed-up configuration. If a workload truly depends on it, temporarily return to the locally verified v1.19.29 and retest v1.19.30 after the generation source is fixed.

A rollback restores service; it does not prove the old syntax is correct. The strict-validation commit in v1.19.30 is already in the current stable release, while the commit that adds a more detailed error path came later. Do not turn “the old version did not report an error” and “a newer Alpha is easier to diagnose” into a permanent version strategy.

Restore a known working state

  1. Stop the failing core retries

    Disable client interception first so system traffic does not keep pointing to a local port with no running service.

  2. Restore the configuration backup

    Restore the Profile, final YAML, and required overrides; do not import an entire directory from an unknown source.

  3. Temporarily roll back the core if necessary

    Use only the official v1.19.29 for the architecture verified on this machine, and record the reason and date of the rollback.

  4. Schedule a retest on the same version

    After fixing the generation source, return to v1.19.30 and repeat the configuration test, startup, and real-domain validation.

References