StackTraces
Meilisearch已验证

Meilisearch primary key 自动推断失败报 index_primary_key_no_candidate_found

@debug_master9 天前更新阅读 6 min00

添加文档时 Meilisearch 报 index_primary_key_no_candidate_found 或 index_primary_key_multiple_candidates_found,根因是未显式指定 primaryKey 且文档中找不到唯一以 id 结尾的字段。解法是在 POST 文档时传 ?primaryKey=字段名,或创建索引时设 primaryKey 参数。适用 Meilisearch 全版本。

Issue & Env(案发现场与环境)

  • 业务场景:往一个新建索引 POST 文档,API 返回 taskUid,但轮询任务状态发现是 failed,错误码是 index_primary_key_no_candidate_found。或者文档里同时有 id 和 author_id 两个字段,报 index_primary_key_multiple_candidates_found。
  • 环境:Meilisearch v1.54.3,curl / 任意 SDK。
  • 关键区分:这不是文档格式错误,也不是字段类型错误,是 Meilisearch 无法从文档字段名中自动推断出 primary key。

StackTrace(堆栈日志)

场景一:文档中没有以 id 结尾的字段。官方文档给出的完整错误响应:

{
    "uid": 1,
    "indexUid": "books",
    "status": "failed",
    "type": "documentAdditionOrUpdate",
    "canceledBy": null,
    "details": {
        "receivedDocuments": 5,
        "indexedDocuments": null
    },
    "error": {
        "message": "The primary key inference failed as the engine did not find any field ending with `id` in its name. Please specify the primary key manually using the `primaryKey` query parameter.",
        "code": "index_primary_key_no_candidate_found",
        "type": "invalid_request",
        "link": "https://docs.meilisearch.com/errors#index-primary-key-no-candidate-found"
    },
    "duration": "PT0.006579S",
    "enqueuedAt": "2026-10-02T10:19:14.464858Z",
    "startedAt": "2026-10-02T10:19:14.465369Z",
    "finishedAt": "2026-10-02T10:19:14.471948Z"
}

场景二:文档中有多个以 id 结尾的字段(如 id 和 author_id):

{
    "uid": 4,
    "indexUid": "books",
    "status": "failed",
    "type": "documentAdditionOrUpdate",
    "canceledBy": null,
    "details": {
        "receivedDocuments": 5,
        "indexedDocuments": 5
    },
    "error": {
        "message": "The primary key inference failed as the engine found 2 fields ending with `id` in their names: 'id' and 'author_id'. Please specify the primary key manually using the `primaryKey` query parameter.",
        "code": "index_primary_key_multiple_candidates_found",
        "type": "invalid_request",
        "link": "https://docs.meilisearch.com/errors#index-primary-key-multiple-candidates-found"
    },
    "duration": "PT0.006002S",
    "enqueuedAt": "2026-10-02T10:44:42.625574Z",
    "startedAt": "2026-10-02T10:44:42.626041Z",
    "finishedAt": "2026-10-02T10:44:42.632043Z"
}

两种情况下文档都不会被索引,indexedDocuments 为 null 或 0。

Reproduce(复现代码)

场景一:文档没有以 id 结尾的字段:

curl -X POST 'http://localhost:7700/indexes/books/documents' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer aSampleMasterKey' \
  --data-binary '[
    {"title": "Solaris", "author": "Stanislaw Lem", "isbn": "978-0156014000"},
    {"title": "Dune", "author": "Frank Herbert", "isbn": "978-0441013594"}
  ]'

# 返回 taskUid,但任务状态为 failed
# 文档字段:title, author, isbn —— 没有以 id 结尾的字段

场景二:文档有多个以 id 结尾的字段:

curl -X POST 'http://localhost:7700/indexes/books/documents' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer aSampleMasterKey' \
  --data-binary '[
    {"id": 1, "title": "Solaris", "author_id": 42},
    {"id": 2, "title": "Dune", "author_id": 43}
  ]'

# 字段:id, title, author_id —— 两个以 id 结尾,无法自动推断

Root Cause(根因分析)

自动推断规则

Meilisearch 要求每个索引有一个 primary key——每个文档中唯一标识自身的字段。如果创建索引时没有显式指定,Meilisearch 会尝试从第一个文档中自动推断。官方文档原文:

Suppose you add documents to an index without previously setting its primary key. In this case, Meilisearch will automatically look for an attribute ending with the string id in a case-insensitive manner (for example, uid, BookId, ID) in your first document and set it as the index’s primary key.

推断逻辑是字段名以 id 结尾(不区分大小写)。匹配的字段如 id、uid、movieId、product_id、ID 都可以作为候选。

两种失败场景

  1. 无候选:文档中没有任何以 id 结尾的字段(如只有 title、author、isbn)。Meilisearch 找不到候选,抛出 index_primary_key_no_candidate_found。
  2. 多候选:文档中有多个以 id 结尾的字段(如 id 和 author_id)。Meilisearch 无法确定用哪个,抛出 index_primary_key_multiple_candidates_found。

两种情况下文档添加任务都会失败,文档不会被索引。这是有意为之——primary key 一旦设定且有文档存在就不能更改,所以推断不确定时宁可不索引。

推断只看第一个文档

Meilisearch 只检查第一批文档的第一个文档对象来确定 primary key。如果第一个文档有 id 字段但后续文档缺少该字段,会报另一个错误 missing_document_id,而不是推断失败。

The Fix(解决方案)

方式一:POST 文档时传 primaryKey 查询参数(最快)

curl -X POST 'http://localhost:7700/indexes/books/documents?primaryKey=isbn' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer aSampleMasterKey' \
  --data-binary '[
    {"title": "Solaris", "author": "Stanislaw Lem", "isbn": "978-0156014000"}
  ]'

primaryKey 参数只在索引为空(首次添加文档)时生效。如果索引已有 primary key,传这个参数不会改变它。

方式二:创建索引时显式指定 primaryKey

curl -X POST 'http://localhost:7700/indexes' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer aSampleMasterKey' \
  --data-binary '{
    "uid": "books",
    "primaryKey": "isbn"
  }'

# 返回 taskUid,等待 task succeeded 后再添加文档

方式三:已有索引用 PATCH 修改 primaryKey

curl -X PATCH 'http://localhost:7700/indexes/books' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer aSampleMasterKey' \
  --data-binary '{"primaryKey": "isbn"}'

注意:primary key 一旦设置且索引中有文档,不能直接更改。必须先删除所有文档,再修改 primary key,再重新添加。

注意事项

  • primary key 值只能是整数或字符串,字符串只能含字母数字(a-z A-Z 0-9)、连字符(-)和下划线(_)。
  • 同一索引内 primary key 值必须唯一,重复值会覆盖之前的文档。
  • 最佳实践:创建索引时就指定 primaryKey,不依赖自动推断,避免首批文档格式不统一导致的推断失败。

References(参考来源)

最后更新于 2026-10-02

这篇帮到你了吗?

刚解决了一个棘手的报错?花两分钟记录下来,帮助下一个遇到同样问题的开发者。

贡献一条解法