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

适用版本: 7.13-7.13

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

feature_states can only be used when all nodes in cluster are version [...] or higher 表示你在创建或恢复包含 feature_states 的快照时,当前集群里至少有一个节点版本还低于该功能所需的最低版本门槛。源码里这属于非常前置的集群版本校验:一旦发现 requestedStates 非空,但 initialMinNodeVersion 低于 FEATURE_STATES_VERSION,就直接通过 SnapshotException 拒绝请求。

常见现象 #

  • 集群处于滚动升级或混部版本阶段时,带 feature_states 的快照/恢复请求立即失败。
  • 普通快照可能能创建,但一旦显式请求 feature states,就在参数预检查阶段被拒绝。
  • 返回信息通常会同时包含“要求的最低版本”和“当前至少有一个节点的较低版本”。

典型报错与异常栈 #

常见日志形态类似下面这样:

SnapshotException[[repo:snap-20260401] feature_states can only be used when all nodes in cluster are version [7.13.0] or higher; but at least one node in this cluster is on version [7.12.1]]

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

feature_states 依赖的是系统索引和内置 feature 元数据的一致表达方式。若集群仍有旧版本节点,它们可能不理解这一套元数据结构,或者无法安全处理 feature-state 相关的快照/恢复语义。因此 Elasticsearch 选择在请求入口直接阻止,而不是冒险在混合版本集群中继续执行。

常见触发场景包括:

  • 集群正在从旧版本滚动升级到支持 feature states 的版本。
  • 节点列表中仍残留一个未升级的数据节点、master 节点或协调节点。
  • 自动化脚本在升级尚未全部完成时,就提前启用了 feature-state 相关快照逻辑。
  • 多集群环境里误把混合版本集群当作已经完成升级的目标集群。

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

建议按下面的顺序排查:

  1. 用节点信息接口确认当前集群里所有节点的实际版本。
  2. 找出最低版本节点,确认它是否仍在服务、是否计划升级或下线。
  3. 核查触发请求时是否显式携带了 feature_states 参数。
  4. 如果集群尚未完成升级,先不要启用 feature-state 相关快照/恢复。
  5. 在所有节点版本达到要求后重新执行请求。

排查时需要注意的问题 #

  • 这不是快照仓库问题,也不是某个索引恢复失败,先看集群版本一致性。
  • 即使只有一个旧节点,也会触发这条校验。
  • 不要用重试掩盖问题;只要旧节点还在,重试结果不会变化。

4. 如何解决这个错误 #

常用修复思路 #

  • 先完成集群全量升级,再使用 feature_states
  • 如果短期无法全量升级,就不要在请求里启用 feature states。
  • 把自动快照逻辑拆分成“基础快照”和“feature-state 快照”两种模式,按集群版本能力切换。
  • 对升级流程增加版本收敛检查,避免业务过早打开新能力。

后续注意事项与推荐建议 #

  • 对 feature-state 请求增加“最低节点版本”预检查。
  • 在运维手册里把 feature states 与版本门槛绑定写清楚。
  • 对滚动升级阶段的快照任务加保护,避免误触新参数。

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

  • INFINI Console 适合查看集群健康度、节点指标、索引状态、错误趋势和请求画像,帮助快速判断异常是局部问题还是系统性问题。
  • INFINI Gateway 适合部署在 Elasticsearch 前面做请求观测、限流、熔断、缓存和流量治理,尤其适合定位高频错误请求、异常重试和不合理 DSL。
  • 如果需要长期治理,建议把异常日志、慢查询、调用来源和变更记录统一接入监控面板,缩短从“发现问题”到“定位根因”的时间。

5. 小结 #

这条错误的本质是集群版本能力还没收敛,feature states 不能提前启用。先升级完成,再使用该能力,是唯一正确的处理顺序。

相关错误 #

附:日志上下文 #

下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题:

}
} else {
    featureStatesSet = Collections.emptySet();
}
} else if (requestedStates.isEmpty() == false) {
    listener.onFailure(new SnapshotException(snapshot; "feature_states can only be used when all nodes in cluster are version ["
        + FEATURE_STATES_VERSION + "] or higher; but at least one node in this cluster is on version ["
        + initialMinNodeVersion + "]"));
    return;
} else {
    featureStatesSet = Collections.emptySet();