為什麼會出現「YAML 解析/unmarshal」錯誤
Clash Meta(現行多與 mihomo 核心並用)啟動時會先把你的設定檔讀進記憶體,再對應到程式內的結構體。這一步若失敗,介面或日誌常出現 yaml unmarshal、cannot unmarshal、mapping key already defined 等字樣,代表檔案仍是文字,但語意已不符合核心預期:可能是縮進錯了、某個鍵重複宣告,或型別對不上(例如該是清單卻變成字串區塊)。這類問題與「規則寫錯導致連不上某站」不同——屬於設定檔根本無法載入,因此用戶端往往直接拒絕啟動或退回上一版設定。若你剛從網路複製片段、合併兩份訂閱匯出結果,或從舊版 Clash 範本改寫,請優先懷疑語法層級的衝突。
第一步:對照日誌裡的「行號」與關鍵字
多數用戶端會在日誌或彈窗中標出大約行號。請用支援顯示行號的編輯器打開同一個 YAML,直接跳到該行附近。常見關鍵字對照如下:mapping key "xxx" already defined at line N 幾乎可確定是同一層重複了同名鍵;did not find expected key 或 block sequence entries are not allowed 多半與縮進混用空白與 Tab、或清單項目前面少了正確層級有關。若訊息寫 cannot unmarshal !!str into []interface {},則可能是把一整段貼在錯誤的縮進底下,導致解析器以為某個欄位應該是「清單」,實際卻變成「純文字區塊」。先別急著改規則內容,先讓檔案能被完整 parse,後續再談分流邏輯。
縮進:YAML 的命門
標準 Clash 設定使用兩個空白作為每一層縮進的慣例(與是否用 Tab 無關,但同一檔案內請勿混用)。proxies、proxy-groups、rules 底下的項目都必須維持一致層級;若你從論壇複製某段 rules:,卻少縮了一格,下一行可能就會被解讀成「新的頂層鍵」,進而與既有的 rules: 衝突或造成結構截斷。實務上建議開啟編輯器的「顯示空白字元」功能,對齊垂直參考線;若某大段怎麼改都報錯,可暫時把該段註解掉(行首加 #),確認檔案其餘部分能啟動後,再分段恢復。
# Bad: mixed indent breaks list structure (illustrative)
proxy-groups:
- name: PROXY
type: select
proxies: # wrong: extra indent makes "proxies" a child of wrong level
- AUTO
上例僅示意常見錯誤:proxies 若多縮或少縮一格,整個群組區塊就會從清單裡「掉出來」。修正方式是對照官方或你信任的範本,逐行把 - name: 與其下欄位對齊到同一父子關係。完成後存檔,再觀察用戶端是否仍報同一行號。
重複鍵:proxy-groups、rules、proxies
YAML 在許多解析器下,同一縮進層級不允許兩次同名頂鍵。實務上最常見的是:使用者先有一份完整的 rules:,後來又從別處貼上另一段也以 rules: 開頭的清單,結果檔案裡出現兩個 rules:。同理,proxy-groups、proxies 若重複宣告,後段可能覆蓋前段,或直接觸發 mapping key already defined 而無法啟動。正確做法是合併為單一區塊:把第二段的條目剪下,貼到第一段清單末尾,並刪除多餘的 rules: 標題行。若兩段規則邏輯衝突,應在同一個 rules: 清單內調整順序,而不是開兩個同名區塊。
少數情況下,訂閱轉換工具會輸出「嵌在註解裡的範例」或重複的 port:、mixed-port:;只要鍵名在同一物件範圍重複,都可能讓 Clash Meta 在 unmarshal 階段失敗。搜尋整份檔案中的 ^rules:、^proxy-groups:(依編輯器語法而定),確認各自只出現一次於頂層(或符合你使用的 profile 結構)。想深入規則語意與排序策略,可另讀本站規則分流詳解;本篇專注在「能成功載入」的前置條件。
合併訂閱與貼上片段:衝突從哪裡來
許多人會把機場訂閱產生的完整設定與自己維護的片段混在一起:例如訂閱已帶入 proxies,你又手動加了一段 proxies: 匯入精簡節點,兩段並存便可能重複鍵或節點名稱衝突。較穩定的做法是選定單一資料來源:要嘛全部走 proxy-providers/訂閱,要嘛只在同一個 proxies 清單內增刪;避免同一檔案出現兩套並列的頂層代理定義。若你使用圖形介面「匯入後再編輯」,也請在儲存前用全文搜尋檢查是否被寫入重複區塊。關於訂閱更新節奏與 proxy-providers 欄位說明,可延伸閱讀訂閱管理實踐一文,與本文的「語法修復」互補。
編碼與編輯器:避免隱形字元
設定檔應以 UTF-8 儲存。若從網頁或通訊軟體複製,有時會帶入智慧引號、全形冒號或不可見的 BOM,導致解析器在某一字元處中斷,錯誤訊息卻指向隔壁行。可嘗試「全選 → 貼到純文字編輯器 → 再貼回」,或改用 VS Code、Neovim 等能顯示非 ASCII 字元的工具。另請確認檔案結尾有換行、且沒有被防毒或同步軟體插入額外說明文字到檔案開頭。
最小可啟動設定與回退策略
當錯誤範圍難以一眼看出時,建議先備份整份 YAML,再建一個最小設定:只保留 port 或 mixed-port、一個空的或極簡的 proxies、一個 select 策略組與幾條 MATCH 規則,確認核心能啟動後,再把原檔中的區塊分批貼回。每貼一大段就存檔測試一次,能最快定位「哪一段」引入結構錯誤。若用戶端支援多設定檔切換,也可把有問題的檔案改名暫存,先載入乾淨範本恢復上網,再慢慢合併。站內功能與文件總覽亦整理各模組概念,方便你對照欄位是否放錯層級。
dns:、tun: 等與你環境綁定的整段設定;先註解、再分段還原,避免從「無法啟動」變成「能啟動但 DNS 外洩或迴圈」。
小結:先救語法,再談規則
Clash Meta 的 YAML 錯誤本質上多是縮進與重複鍵兩類;日誌中的 unmarshal 關鍵字與行號是最直接的線索。養成單一 rules/proxy-groups 區塊、統一空白縮進、合併訂閱而非重複貼上同名頂鍵,就能排除絕大多數「配置無法啟動」的情況。相比反覆嘗試不同節點,先把設定檯面清乾淨,反而更省時間。若你希望用圖形介面減少手改檔案的頻率,可選擇與 mihomo 整合良好、具備語法提示或設定預覽的用戶端——在穩定性與可維護性上,通常比純文字硬改更不容易留下隱性語法地雷。
實務上建議每次大改前都保留時間戳記備份,並用行號對照日誌;一旦能穩定啟動,再逐步加回進階模組。