📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

适用版本: 7.16-8.9

1. 错误异常的基本描述 #

index [index] has no active shard copy 表示 Elasticsearch 在为某个索引选择可执行请求的分片副本时,没有找到任何活动中的 shard copy。它通常出现在搜索、读取或需要访问该索引数据的操作中,本质上是“当前没有任何可用分片副本可以处理这个索引”。

常见现象 #

  • 读请求或搜索请求针对某个索引失败,而其他索引可能正常。
  • 集群可能处于 yellowred,对应索引存在未分配分片。
  • 日志里常伴随 NoShardAvailableActionException、分片分配失败、节点离线或恢复中异常。

典型报错与异常栈 #

org.elasticsearch.action.NoShardAvailableActionException: index [orders-2026.03] has no active shard copy

2. 为什么会发生这个错误 #

从执行路径看,Elasticsearch 会先通过 operationRouting().searchShards(...) 找出该索引所有可用分片。如果结果为空,就说明没有任何活动主分片或副本分片可供请求使用。常见原因包括:

  • 主分片和副本分片都尚未分配或仍在恢复中。
  • 承载该索引分片的节点离线,且没有其他节点持有可用副本。
  • 分片因磁盘水位、分配过滤、节点角色限制等原因无法变成 active。
  • 索引刚创建或刚恢复,分片尚未完成启动,但上游请求已经打进来。

3. 如何排查和解决这个异常和解决这个异常 #

重点是确认该索引为什么没有任何活动分片。

  1. 查看索引和分片状态:
GET /_cat/shards/orders-2026.03?v
GET /_cluster/health/orders-2026.03?level=shards
  1. 如果有未分配分片,使用分配解释接口定位原因:
GET /_cluster/allocation/explain
  1. 检查相关节点是否在线、磁盘是否超水位、是否存在分配过滤规则。
  2. 如果索引来自恢复或重分配,确认分片是否仍处于初始化或恢复中。
  3. 如果没有任何可恢复副本,回溯是否需要从快照恢复或接受空分片重建。

排查时需要注意的问题 #

  • 这不是简单的“索引不存在”,而是索引存在但当前没有可用 shard copy。
  • 如果只有单个索引报错,问题往往集中在该索引的分片分配,而不是整个集群完全不可用。
  • 对读请求来说,哪怕索引元数据还在,只要没有活动分片,依然无法服务。

4. 如何解决这个错误 #

常用修复思路 #

  • 如果分片只是尚未恢复完成,等待恢复或修复导致恢复卡住的原因。
  • 如果是节点离线导致无活动分片,优先恢复节点或让副本重新分配。
  • 如果受磁盘水位或分配规则限制,调整相应设置后让分片重新分配。
  • 如果已经没有可用 shard copy,只能从快照恢复,或在确认风险后重建空分片。

相关 Elasticsearch API #

  • GET /_cat/shards/{index}?v:查看分片状态。
  • GET /_cluster/health/{index}?level=shards:查看索引级健康状态。
  • GET /_cluster/allocation/explain:分析分片不可分配原因。

借助 INFINI 产品提升排障效率 #

  • INFINI Console 可以关联索引健康、分片分布、节点状态和恢复日志,快速锁定故障点。
  • INFINI Gateway 可帮助确认哪些查询持续命中无活动分片的索引,便于临时隔离流量。

5. 小结 #

index [index] has no active shard copy 的关键是“索引存在,但没有任何活动分片副本可用”。排查时应回到分片状态、节点可用性和分配原因,而不是停留在表面的搜索失败信息上。

相关错误 #

附:日志上下文 #

for (String index : indices) {
	final GroupShardsIterator shardIts = clusterService.operationRouting()
		.searchShards(clusterState, new String[] { index }, null, null, null, null);
	final IndexSelector indexResult = new IndexSelector(shardIts);
	if (indexResult.nodeToShards.isEmpty()) {
		onIndexFailure.accept(index, new NoShardAvailableActionException(null, "index [" + index + "] has no active shard copy"));
	}
}