适用版本: 6.8-8.9
1. 错误异常的基本描述 #
all shards failed 是 Elasticsearch 搜索阶段的汇总性异常,表示这次查询命中的所有目标分片都没有成功返回结果。它通常不是最原始的错误,而是协调节点在汇总各分片执行结果时给出的最终结论。真正的根因往往藏在 failed_shards 里的具体异常里,例如字段类型不支持、聚合执行失败、脚本报错、分片不可用、索引关闭或节点异常。
这类错误最容易误判的地方在于,用户往往只看到一句 all shards failed,但真正需要排查的是“为什么每个分片都失败了”。因此定位时不能停留在报错标题,而要继续向下看失败分片的索引名、分片号、异常类型和具体 reason。
常见现象 #
- 在执行
_search、Kibana 可视化、大盘查询或带聚合的检索请求时,接口直接返回search_phase_execution_exception,其中reason为all shards failed。 - 返回体中通常会带有
failed_shards数组,里面列出失败的索引、分片编号和分片级错误原因;如果跨多个索引查询,往往多个分片会因为同一种 DSL 或字段问题一起失败。 - 某些查询在小范围索引或测试环境正常,但在生产环境、长时间范围或跨索引查询时失败,这通常说明问题与字段映射不一致、历史脏数据或部分分片状态异常有关。
- 从业务侧看,典型表现包括搜索页无结果、可视化报表打不开、聚合统计失败、告警规则查询报错,而不是单纯的“节点连不上”。
典型报错与异常栈 #
这类错误常与下面这些异常一起出现:
search_phase_execution_exceptionquery_shard_exceptionaggregation_execution_exceptionillegal_argument_exceptionscript_exceptionindex_closed_exceptionno_shard_available_action_exception
常见日志形态通常类似下面这样:
{
"error": {
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"failed_shards": [
{
"shard": 0,
"index": "logs-2026.03.31",
"reason": {
"type": "illegal_argument_exception",
"reason": "Fielddata is disabled on text fields by default"
}
}
]
},
"status": 400
}
也可能在服务端日志中看到类似堆栈:
SearchPhaseExecutionException: all shards failed
Caused by: QueryShardException / AggregationExecutionException / ScriptException
at org.elasticsearch.action.search...
2. 为什么会发生这个错误 #
这个错误的本质不是“所有分片同时坏了”,而是“这条查询对所有命中的分片都不成立或都执行失败了”。如果 DSL 本身有问题、字段不支持当前查询能力、跨索引 mapping 不一致,或者命中的分片本身不可用,那么每个分片都会独立失败,最终由协调节点统一汇总为 all shards failed。
常见原因通常包括:
- 对
text字段做排序、聚合或脚本访问,而字段本身没有开启fielddata,或者应该使用.keyword子字段却误用了主字段。 - 跨多个索引查询时,同名字段在不同索引上的 mapping 不一致,例如一个索引是
keyword,另一个是text或long,导致所有相关分片都无法按同一种逻辑执行。 - 查询命中了关闭索引、不可用分片、恢复中的分片,或者集群处于
red/异常迁移状态,导致所有目标分片都没有返回有效结果。 - 使用了错误的聚合、脚本、nested 路径或不兼容的查询子句,导致每个分片都会在本地执行阶段抛出相同异常。
- 节点资源异常,例如 JVM 堆紧张、断路器触发、线程池拥塞、底层 IO 问题,导致查询在所有相关分片上都失败。
3. 如何排查和解决这个异常和解决这个异常 #
建议按“先拿到失败分片明细,再缩小查询范围,最后确认是 DSL 问题还是分片状态问题”的顺序处理:
- 保留原始
_search请求和完整错误返回,重点提取failed_shards中的index、shard、type、reason。 - 缩小查询范围,例如先查单个索引、较短时间范围,判断是所有索引都失败,还是某个索引家族有问题。
- 检查字段 mapping 和 field caps,确认参与排序、聚合、脚本或过滤的字段在所有命中索引上是否一致可用。
- 再看集群健康度、分片分布和节点资源,确认是否存在未分配分片、关闭索引或节点压力异常。
- 如果查询里用了复杂聚合、脚本或 nested,优先逐步删减 DSL,找出最小触发条件。
相关 Elasticsearch API 及调用说明 #
下面这些接口最适合排查 all shards failed。建议从原始查询和 failed_shards 入手,再核对字段能力、分片状态和节点资源。
1. 复现原始搜索请求 #
用于确认是哪条查询导致所有分片失败。
curl -X GET "http://localhost:9200/my_index/_search?pretty" \
-H 'Content-Type: application/json' \
-d '{
"query": {
"match": {
"message": "error"
}
},
"aggs": {
"by_host": {
"terms": {
"field": "host.name"
}
}
}
}'
重点不是只看顶层报错,而是查看返回体里的 failed_shards。
2. 校验字段能力 #
用于确认跨索引查询时,同名字段是否都支持聚合、排序或搜索。
curl -X GET "http://localhost:9200/logs-*/_field_caps?fields=host.name,message,user.keyword&pretty"
重点关注:
- 字段在不同索引上是否类型一致。
- 是否同时出现
text、keyword、long等不兼容类型。 - 字段是否支持
aggregatable、searchable。
3. 查看字段 mapping #
如果怀疑某个字段在部分索引上 mapping 漂移,可以直接查看:
curl -X GET "http://localhost:9200/logs-*/_mapping/field/host.name?pretty"
如果问题字段很明确,这个接口比看完整 _mapping 更高效。
4. 校验查询是否合法 #
用于先排除明显的 DSL 结构问题。
curl -X GET "http://localhost:9200/my_index/_validate/query?pretty&explain=true" \
-H 'Content-Type: application/json' \
-d '{
"query": {
"match": {
"message": "error"
}
}
}'
这个接口不能替代真实搜索执行,但可以先排掉部分结构错误。
5. 查看集群健康状态 #
用于判断问题是否和分片整体状态有关。
curl -X GET "http://localhost:9200/_cluster/health?pretty"
重点关注:
status是否为yellow或red。unassigned_shards是否大于0。relocating_shards、initializing_shards是否异常偏高。
6. 查看分片分布和状态 #
用于确认失败是否集中在某些索引或节点。
curl -X GET "http://localhost:9200/_cat/shards?v"
如果已定位到具体索引:
curl -X GET "http://localhost:9200/_cat/shards/my_index?v"
重点关注:
- 是否存在
UNASSIGNED、INITIALIZING、RELOCATING。 - 失败分片是否集中在同一节点。
- 主分片是否正常
STARTED。
7. 查看未分配分片解释 #
如果有未分配分片,可以继续看原因:
curl -X GET "http://localhost:9200/_cluster/allocation/explain?pretty" \
-H 'Content-Type: application/json' \
-d '{
"index": "my_index",
"shard": 0,
"primary": true
}'
这个接口适合确认是磁盘水位、节点过滤条件,还是恢复失败导致分片不可用。
8. 查看节点资源状态 #
用于判断搜索失败是否与 JVM、断路器或线程池压力有关。
curl -X GET "http://localhost:9200/_nodes/stats/jvm,fs,thread_pool,breaker?pretty"
重点关注:
breaker是否频繁触发。- 搜索线程池是否积压。
- 个别节点是否存在明显的堆或磁盘异常。
9. 查看热点线程或任务 #
如果查询很慢后才报 all shards failed,可以进一步看:
curl -X GET "http://localhost:9200/_nodes/hot_threads?pretty"
curl -X GET "http://localhost:9200/_tasks?pretty&actions=*search"
这两个接口适合判断是否存在高开销查询、脚本热点或长期阻塞的搜索任务。
排查时需要注意的问题 #
- 不要把
all shards failed当成根因,它只是最终汇总结果;真正需要看的永远是failed_shards.reason。 - 如果查询跨多个时间分区索引,先缩小索引范围通常能最快定位是哪个索引的 mapping 或数据有问题。
- 如果是 Kibana 或上层应用拼装的查询,务必抓取最终发往 Elasticsearch 的原始 DSL,而不是只看业务代码里的模板。
4. 如何解决这个错误 #
常用修复思路 #
- 如果根因是字段类型或字段能力不匹配,优先改用正确字段,例如从
text改为keyword,必要时通过重建索引统一 mapping。 - 如果根因是查询 DSL 过重或写法错误,先简化聚合、排序和脚本逻辑,确认最小可用查询后再逐步恢复功能。
- 如果根因是分片或索引状态异常,先恢复分片可用性、重新分配或处理关闭索引,再恢复查询。
- 如果根因是节点资源不足,先缓解 JVM、线程池和断路器压力,必要时扩容节点或对高风险搜索流量做限流。
后续注意事项与推荐建议 #
- 为跨索引查询建立字段规范和模板约束,尽量避免同名字段在不同索引上出现不同类型。
- 对高频聚合、脚本查询和复杂报表建立上线前检查,避免高风险 DSL 直接进入生产环境。
- 为
failed_shards、慢查询、断路器和分片异常建立告警,尽量在用户看到all shards failed之前就发现问题。
借助 INFINI 产品提升排障效率 #
- INFINI Console 适合同时观察分片健康、节点资源、慢查询和失败趋势,快速判断这是单个索引问题还是全局查询问题。
- INFINI Gateway 适合在入口侧采样原始 DSL,请求失败时可以更快回溯到底是哪类查询触发了
all shards failed。 - 如果这类问题反复出现,建议把失败 DSL、来源应用、目标索引和失败分片信息统一沉淀为排障画像,后续定位会快很多。
5. 小结 #
all shards failed 不是一个具体的底层故障类型,而是“所有目标分片都失败了”这一最终结果。真正的排查重点永远是失败分片里的具体异常、涉及的字段、相关索引和分片状态。
只要坚持“先看 failed_shards,再查 mapping 与分片,再判断资源与 DSL”这条路径,这类问题通常都能很快缩小范围。对于频繁出现的场景,结合 INFINI Console 和 INFINI Gateway 做查询观测与索引治理,会比事后被动排查更有效。
相关错误 #
- index is unrecoverable:底层索引已损坏到无法作为恢复来源
- failed to fetch index version after copying it over:分片复制完成后索引目录仍不可读
- recovery was canceled reason [reason]:分片恢复流程被系统中止
- recover snapshot files cancelled:快照文件恢复阶段被取消
- cannot restore partial index:恢复中断后可能遗留不完整目标索引
附:日志上下文 #
下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题:
SearchPhaseExecutionException: all shards failed
at org.elasticsearch.action.search.AbstractSearchAsyncAction.onPhaseFailure(...)
at org.elasticsearch.action.search.SearchScrollAsyncAction...
Caused by: [index_name][shard_id] ShardSearchFailure
...





