Skip to main content
EN

Home / Blog / Config Basics

Clash config error reference — common YAML mistakes and core error messages

Config Basics2026-05-161440 words3 min read
Clash config error reference — common YAML mistakes and core error messages

You save an edited config, the client flashes one line of English, and that is all you get. This turns the common errors into a reference.

First, run a config check

After editing and before importing, let the core validate it:

mihomo -t -d /path/to/config/dir

-t is test mode: it checks without running. Its messages are far more detailed than a client dialog, and it usually tells you which line is wrong.

Clash Verge users can run that command against config.yaml in the config directory. Where that directory is:

PlatformPath
Windows%APPDATA%\io.github.clash-verge-rev.clash-verge-rev
macOS~/Library/Application Support/io.github.clash-verge-rev.clash-verge-rev
Linux~/.local/share/io.github.clash-verge-rev.clash-verge-rev

1. YAML syntax errors

These fail during parsing, and the message usually carries a line number.

found character that cannot start any token

Cause: a tab used for indentation. YAML accepts spaces only.

Locating it: turn on "render whitespace" in your editor; tabs show as arrows.

Fix: replace them all with spaces. In VS Code, Ctrl+Shift+P → "Convert Indentation to Spaces".

mapping values are not allowed in this context

Cause: no space after a colon, or an unquoted colon inside a value.

# wrong
port:7890
name: HK: 01

# right
port: 7890
name: "HK: 01"

did not find expected key / could not find expected ':'

Cause: inconsistent indentation.

# wrong: two keys at different indents
proxies:
  - name: "A"
    type: trojan
     server: a.com      # ← one space too many

# right
proxies:
  - name: "A"
    type: trojan
    server: a.com

found unexpected end of stream

Cause: an unclosed quote, or a truncated file.

Check that every quote is paired; if the config was downloaded, it may not have finished.

Special characters in a password

# dangerous: # starts a comment, and @ and : can also cause trouble
password: p@ss#word

# right
password: "p@ss#word"

2. Field and structure errors

The syntax is fine, but the core does not recognise what you wrote.

unmarshal error / cannot unmarshal !!str into int

Cause: the wrong type, such as a port written as a string.

# wrong
port: "443"      # some fields strictly require a number

# right
port: 443

Conversely, UUIDs and passwords have to be strings:

uuid: 12345678-1234-1234-1234-123456789012      # may parse as something odd
uuid: "12345678-1234-1234-1234-123456789012"    # safe

unsupported proxy type: xxx

Cause: the subscription uses a protocol your current core does not support.

Fix: update the Mihomo core. In Clash Verge: Settings → Clash Core → update.

If it is still unsupported after updating, Mihomo genuinely has not implemented that protocol yet and you will need a node using a different one from your provider.

proxy 'xxx' not found

Cause: a policy group references a node name that does not exist.

Common triggers:

  • A typo when writing node names by hand
  • A subscription update renamed the nodes
  • A group name in the extended config does not match the subscription (emoji or spacing differences)

Fix: open the original subscription file and copy the exact name. Or switch to include-all plus filter for automatic collection; see node grouping regex.

rule 'xxx' error: invalid domain

Cause: the rule is malformed.

# wrong
- DOMAIN-SUFFIX,https://google.com,PROXY   # no protocol
- DOMAIN-SUFFIX,*.google.com,PROXY         # no wildcards
- IP-CIDR,8.8.8.8,DIRECT                   # IP-CIDR requires a mask

# right
- DOMAIN-SUFFIX,google.com,PROXY
- IP-CIDR,8.8.8.8/32,DIRECT,no-resolve

rules[N] [xxx] error: unsupported rule type

Cause: a misspelled rule type, or one your core version does not support.

Check the spelling: DOMAIN-SUFFIX not DOMAIN_SUFFIX, IP-CIDR not IPCIDR.

Circular references between policy groups

Symptom: loading hangs, or the message mentions recursion.

Cause: group A's proxies contain B while group B's contain A.

Fix: sort out the hierarchy so references only go one way (upper groups reference lower ones, never the reverse).

A domain in default-nameserver

# wrong
default-nameserver:
  - https://doh.pub/dns-query

# right: must be plain IPs
default-nameserver:
  - 223.5.5.5
  - 119.29.29.29

The whole purpose of default-nameserver is resolving the hostnames of your other DNS servers, so it cannot itself be a hostname.

Internal names will not resolve

Not an error, just wrong behaviour. The cause is fake-ip catching them.

dns:
  fake-ip-filter:
    - "+.mycompany.com"
    - "*.lan"
    - "*.local"

See DNS configuration explained.

4. Rule sets and providers

provider xxx: initial failed

Cause: a rule set or subscription failed to download.

Investigation:

Check in orderDoes the url open in a browserDoes the cache file at path exist, and what is in itAdd a proxy field to the provider so the download goes through a nodeDoes the provider filter by User-Agent (add a header specifying clash.meta)Is the disk writable (permissions on the directory holding path)

The rule set loads but does nothing

Cause: behavior does not match the file contents. This produces no error, it just fails silently.

behavior must corresponddomainthe file is a plain google.com+.youtube.comipcidrthe file is IP range1.0.1.024classicalthe file is full rulDOMAIN-SUFFIX,google.com
Open the cache file named by path and one glance tells you which to use

rule-set xxx not found

The rule set name is referenced in rules but not defined in rule-providers, or the name is misspelled.

5. TUN and permissions

operation not permitted / the TUN switch does nothing

Cause: insufficient privileges, so the virtual adapter could not be created.

Fix:

  • Windows / macOS: install "service mode"
  • Linux: sudo setcap cap_net_admin,cap_net_bind_service=+ep /path/to/mihomo

address already in use

The port is taken.

# Windows
netstat -ano | findstr :7897
tasklist | findstr <PID>
# Linux / macOS
lsof -i :7897

Change the port or stop the process holding it.

6. A fast way to locate the problem

When the config is long and the error carries no line number, bisect it:

BisectingCut the config in halfkeep proxies and a minimal rules sectionDoes it loadif yes, the problem is in the half you removedHalve againnarrowing the range step by stepLand on the specific sectionusually a few rounds is enough
Far faster than reading line by line, especially in a subscription config of several thousand lines

A minimal working config to use as a baseline:

mixed-port: 7897
mode: rule
log-level: info
proxies:
  - name: "TEST"
    type: trojan
    server: example.com
    port: 443
    password: "pwd"
proxy-groups:
  - name: "PROXY"
    type: select
    proxies: ["TEST", DIRECT]
rules:
  - MATCH,PROXY

If that loads, your environment is fine and the problem is in your config's content.

7. The error reference table

Error keywordCauseFix
cannot start any tokenA tab was usedReplace with spaces
mapping values are not allowedNo space after a colon, or a colon in a valueAdd a space, or quote it
did not find expected keyInconsistent indentationAlign the indentation
unexpected end of streamUnclosed quote or incomplete fileCheck quotes, download again
unmarshal errorType mismatchNumbers unquoted, strings quoted
unsupported proxy typeProtocol unsupportedUpdate the core
proxy not foundNode name reference wrongCopy the exact name from the subscription
unsupported rule typeRule type misspelledCheck hyphens and capitalisation
invalid domainMalformed rule contentRemove protocol prefixes and wildcards
provider initial failedDownload failedCheck the url, add proxy and UA
address already in usePort takenChange the port or stop the process
operation not permittedInsufficient privilegesInstall service mode, or setcap
Rule set silently ineffectivebehavior mismatchOpen the cache file and compare

8. Prevention

Habits that avoid troubleBack up before editing a configUse an editor with YAML syntax highlighting (VS Code plus the YAML extension)Run mihomo -t after editingUse the extended config (Merge) rather than editing the subscription fileQuote every stringAdd ExecStartPre to the systemd service for a config check, so a broken config cannot displace a running service

In short

  • mihomo -t -d directory is the single most useful command; its errors beat the client's
  • The three YAML traps: tab indentation, a missing space after a colon, and an unclosed quote
  • proxy not found usually means a name mismatch — copy it from the subscription
  • A rule set that fails silently means the behavior is wrong
  • When you cannot locate it, bisect the config

Related: the YAML structure explained and the Merge extended config.


Related docs