在 search 請求體裡給
locales傳了"chinese"、"cn"這類人類習慣叫法,Meilisearch 直接返回 400,錯誤碼invalid_search_locales。locales只認官方 ISO-639 取值,中文的合法值是zh、zho、cmn,沒有cn也沒有chinese。另外查詢側locales的優先級高於索引側localizedAttributes,寫錯會覆蓋掉索引裡配好的語言。
Issue & Env(案發現場與環境)
- 觸發場景:在
POST /indexes/{uid}/search的請求體裡顯式指定locales來告訴 Meilisearch 查什麼語言,中文按口語/國家碼寫成了"chinese"或"cn"。 - 環境:Meilisearch v1.54.3,本機實跑復現。curl / 任意 SDK 只要把
locales裡塞了非法值都會觸發。 - 關鍵區分:這是一個同步返回的 400 校驗錯誤,不是異步任務失敗。請求根本沒進搜索流程,被參數校驗攔下了。合法的
locales請求能正常返回命中(本機搜{"q":"三体","locales":["cmn"]}命中 id 1)。
StackTrace(堆疊日誌)
locales: ["chinese"] 的返回原文(message 裡的語言清單很長,中間截斷為 ...):
{"message":"Unknown value `chinese` at `.locales[0]`: expected one of `af`, `ak`, `am`, `ar`, ... `zh`, `zu`, `afr`, ... `zho`, `zul`, `cmn`","code":"invalid_search_locales","type":"invalid_request","link":"https://docs.meilisearch.com/errors#invalid_search_locales"}
locales: ["cn"] 是同一個錯誤碼,只是把值換掉:
{"message":"Unknown value `cn` at `.locales[0]`: expected one of `af`, `ak`, `am`, `ar`, ...","code":"invalid_search_locales","type":"invalid_request","link":"https://docs.meilisearch.com/errors#invalid_search_locales"}
注意報錯裡的路徑是 .locales[0](查詢側)。索引側設置寫錯非法 locale 時,錯誤碼是另一個:invalid_settings_localized_attributes,路徑是 [0].locales[0],別把兩者看成一回事。
Reproduce(復現程式碼)
# 合法:cmn 是中文的合法取值之一,正常返回命中
curl -s -X POST http://localhost:7700/indexes/books_zh/search \
-H 'Authorization: Bearer aSampleMasterKey' \
-H 'Content-Type: application/json' \
-d '{"q":"三体","locales":["cmn"]}'
# 非法:chinese —— 返回 400 invalid_search_locales
curl -s -X POST http://localhost:7700/indexes/books_zh/search \
-H 'Authorization: Bearer aSampleMasterKey' \
-H 'Content-Type: application/json' \
-d '{"q":"三体","locales":["chinese"]}'
# 非法:cn —— 同样 400 invalid_search_locales
curl -s -X POST http://localhost:7700/indexes/books_zh/search \
-H 'Authorization: Bearer aSampleMasterKey' \
-H 'Content-Type: application/json' \
-d '{"q":"三体","locales":["cn"]}'
Root Cause(根因分析)
locales 只接受 ISO-639 取值
locales 不是自由文本,它按 ISO-639 標準校驗。英文裡可以寫 en/eng,中文對應的合法值是 zh、zho、cmn(cmn 是「官話」的 ISO 639-3 碼)。cn 是國家碼不是語言碼,chinese 是英文名也不是合法取值,兩者都會在校驗層被拒。
查詢側 locales 會覆蓋索引側設置
這點比報錯本身更容易被忽略:索引側可以通過 localizedAttributes 聲明「哪個字段是什麼語言」,而查詢側的 locales 優先級更高。如果索引裡已經把 *_zh 聲明成 cmn,查詢時又隨手傳了個錯的 locales,不僅會 400,即便僥倖寫了個別的合法 locale,也可能蓋掉索引裡的語言聲明,導致分詞行為和你預期不一致。要麼兩側對齊,要麼查詢側乾脆不傳、交給索引設置。
報錯信息裡能直接讀到合法值
錯誤 message 會把可接受取值整段列出來(af, ak, … zh, zu, afr, … zho, zul, cmn)。中文相關的就三個:zh、zho、cmn。不用去翻文檔,報錯裡就寫著。
The Fix(解決方案)
第一步:把 locales 改成合法值
中文用 cmn(或 zh/zho):
curl -s -X POST http://localhost:7700/indexes/books_zh/search \
-H 'Authorization: Bearer aSampleMasterKey' \
-H 'Content-Type: application/json' \
-d '{"q":"三体","locales":["cmn"]}'
第二步:確認索引側聲明與查詢側一致
查詢側要傳 locales 時,先核對索引裡 localizedAttributes 是怎麼聲明的,讓兩側語言碼對上:
curl -s http://localhost:7700/indexes/books_zh/settings/localized-attributes \
-H 'Authorization: Bearer aSampleMasterKey'
第三步:能不傳就不傳
如果索引已經用 localizedAttributes 配好了每種字段的語言,大多數情況下查詢側不需要再傳 locales,讓它走索引設置即可,省掉一類寫錯值的風險。
排查提示
- 看到
invalid_search_locales先看報錯裡的路徑:.locales[0]是查詢側;[0].locales[0]是索引側設置(對應invalid_settings_localized_attributes)。 - 國家碼(
cn、us)、英文名(chinese、english)都不是合法值,用 ISO-639。 - 單個請求可以傳多個 locale,按陣列順序生效;任何一個非法,整條請求都 400。
References(參考來源)
- Search with POST — Meilisearch 官方文檔meilisearch-docs
- Error codes — Meilisearch 官方文檔meilisearch-docs
- Settings — Meilisearch 官方文檔meilisearch-docs
