适用版本: 7.12-8.9
1. 错误异常的基本描述 #
the feature_states value [none] indicates that no feature states should be restored; but other feature states were requested 表示 restore 请求里的 feature_states 参数自相矛盾。none 的语义是“不恢复任何 feature state”,而同一个数组里又出现了其他具体 feature 名称,Elasticsearch 在解析 restore 请求时就会直接抛出 SnapshotRestoreException。
这类错误与快照内容、仓库状态和节点能力无关,本质上是请求参数构造错误。
常见现象 #
- restore 请求在参数校验阶段立即失败,不会进入后续恢复流程。
- 常见错误写法是
"feature_states": ["none", "security"]。 - 自动化平台或脚本经常把“默认不恢复 feature state”和“按需恢复部分 feature”两套逻辑拼到同一请求中。
- 由于它是前置参数错误,重试同样的请求不会有任何帮助。
典型报错与异常栈 #
SnapshotRestoreException[[repo:snap-20260401] the feature_states value [none] indicates that no feature states should be restored; but other feature states were requested: [none, security]]
2. 为什么会发生这个错误 #
源码会先把 restore 请求中的 requestedFeatureStates 转换为集合。如果集合里包含 NO_FEATURE_STATES_VALUE,也就是 none,同时又有其他值,就会直接抛出这条异常。也就是说,Elasticsearch 把 none 视为一个排他性的特殊模式,而不是一个可以和普通 feature 名称并列的枚举值。
常见原因通常包括:
- 代码默认注入了
none,用户又在上层配置里追加了具体 feature。 - UI 同时保存了“不要恢复 feature state”和“勾选要恢复的 feature”两种状态。
- 多个模板或中间件层叠生成 restore 请求时,没有做互斥检查。
- 只做了数组去重,但没有做语义校验。
3. 如何排查和解决这个异常和解决这个异常 #
建议按“先看最终请求,再确认参数来源”的顺序排查:
- 抓取最终提交到 Elasticsearch 的 restore 请求 JSON。
- 检查
feature_states是否同时包含none和其他值。 - 回溯参数来源,确认是默认模板、UI 配置还是脚本拼装逻辑注入了冲突值。
- 根据真实需求二选一:要么只传
none,要么只传具体 feature 名称。 - 修复请求构造逻辑后再重新执行 restore。
相关 Elasticsearch API 及调用说明 #
1. 错误示例 #
curl -X POST "http://localhost:9200/_snapshot/my_repo/my_snapshot/_restore?pretty" \
-H 'Content-Type: application/json' \
-d '{
"indices": "logs-*",
"feature_states": ["none", "security"]
}'
这个请求会直接失败,因为 none 与 security 不能同时出现。
2. 仅不恢复 feature state 的正确写法 #
curl -X POST "http://localhost:9200/_snapshot/my_repo/my_snapshot/_restore?pretty" \
-H 'Content-Type: application/json' \
-d '{
"indices": "logs-*",
"feature_states": ["none"]
}'
3. 只恢复部分 feature state 的正确写法 #
curl -X POST "http://localhost:9200/_snapshot/my_repo/my_snapshot/_restore?pretty" \
-H 'Content-Type: application/json' \
-d '{
"indices": "logs-*",
"feature_states": ["security", "ilm"]
}'
排查时需要注意的问题 #
- 这不是“快照里没有该 feature”,而是请求本身语义互斥。
- 即使数组去重后每个值都唯一,只要
none与其他值并存,仍然非法。 - 如果上游系统有全局开关和多选框,最好在 UI 层就阻止用户选择冲突组合。
4. 如何解决这个错误 #
常用修复思路 #
- 如果你不想恢复任何 feature state,就只传
none。 - 如果你需要恢复部分 feature state,就移除
none,仅保留具体名称。 - 在 restore 请求构造层增加互斥校验,防止冲突参数进入生产。
- 为自动化平台增加“最终请求预览”或 lint 规则,提前拦截错误组合。
后续注意事项与推荐建议 #
- 把
feature_states封装成更明确的模式开关,而不是直接拼接裸数组。 - 对 restore 自动化脚本增加单元测试,覆盖
none与具体 feature 的冲突场景。 - 把这类参数冲突归类为“可预防错误”,优先在调用侧消灭,而不是依赖服务端报错兜底。
借助 INFINI 产品提升排障效率 #
- INFINI Console 可帮助追踪 restore 请求失败分布,识别是否某条模板化流程持续发送冲突参数。
- INFINI Gateway 适合记录请求体和调用来源,快速定位是哪一个自动化入口生成了非法
feature_states。
5. 小结 #
the feature_states value ... 的根因不是 Elasticsearch 恢复能力不足,而是请求参数自己打架了。修复方式很简单:none 和其他 feature 二选一,不要同时传。
相关错误 #
- requested feature states:请求指定的 feature state 不在快照中
- requested feature states … are present in snapshot but those features are not installed on the current master node:快照里有,但当前 master 不支持
- failed to restore snapshot [snapshotId]:参数校验通过后,真正执行阶段仍可能失败
附:日志上下文 #
final Set requestedStates = org.elasticsearch.common.collect.Set.of(requestedFeatureStates);
if (requestedStates.contains(NO_FEATURE_STATES_VALUE)) {
throw new SnapshotRestoreException(snapshot; "the feature_states value [" + NO_FEATURE_STATES_VALUE +
"] indicates that no feature states should be restored; but other feature states were requested: " + requestedStates);
}
```---
title: "feature states 值错误 - 如何解决此 Elasticsearch 异常"
date: "2026-01-06T08:00:00+08:00"
blogAuthor: "INFINI Labs"
category: "elasticsearch_errors"
blogAuthorDesc: "追求极致,无限可能。"
tags: ["快照恢复", "feature states", "版本不匹配", "异常处理"]
blogImage: "/img/blog/request-logging/bg.png"
description: "featurestates值错误是Elasticsearch常见异常,本文围绕查询解析、执行或结果归并链路说明常见现象、原因分析、排查步骤、修复方案与后续优化建议。"
lang: "cn"
layout: "infini/knowledge-detail"
---
> **适用版本:** 7.12-7.13
## 1. 错误异常的基本描述
这里的 `the feature_states value [...] indicates that no feature states should be restored; but other feature states were requested` 指的是你在 restore 请求中把 `none` 这类“不要恢复任何 feature states”的哨兵值,与其他具体 feature state 名称同时传入了。源码会先把 `requestedFeatureStates` 转为集合;如果集合同时包含 `NO_FEATURE_STATES_VALUE` 和其他值,就立刻抛出 `SnapshotRestoreException`。
### 常见现象
- 恢复请求在参数解析完成后立即失败,不会真正进入索引恢复阶段。
- 常见请求形态是同时传了 `feature_states: ["none", "security"]` 之类的组合。
- 这类错误多发生在自动化脚本把“默认禁用”和“显式恢复部分 feature”两套逻辑混到一起时。
### 典型报错与异常栈
常见日志形态类似下面这样:
```text
SnapshotRestoreException[[repo:snap-20260401] the feature_states value [none] indicates that no feature states should be restored; but other feature states were requested: [none, security]]
2. 为什么会发生这个错误 #
none 这类特殊值的语义是“不要恢复任何 feature states”。一旦它出现,请求就不应该再包含其他具体 feature 名称。Elasticsearch 在这里做的是语义互斥校验,而不是检查 feature 是否存在。
常见触发场景包括:
- 脚本默认注入了
none,同时用户又额外指定了具体 feature。 - UI 或配置中心把“禁用恢复 feature states”与“选择要恢复的 feature”同时保存。
- 请求构造层对 feature_states 做了去重前拼接,但没处理语义冲突。
- 多层封装各自追加参数,最终合成了互斥值集合。
3. 如何排查和解决这个异常和解决这个异常 #
建议按下面的顺序排查:
- 查看最终 restore 请求中的
feature_states数组。 - 确认是否同时存在
none和其他 feature 名称。 - 回溯是谁注入了
none,是默认配置、模板,还是调用方代码。 - 根据目标语义二选一:要么完全不恢复 feature states,要么只列出具体要恢复的 feature。
- 修复后重新提交 restore 请求。
排查时需要注意的问题 #
- 这不是“feature 不存在”,也不是“节点版本不够”,而是参数本身语义自相矛盾。
- 不要只做数组去重;
none与其他值即使都唯一,仍然非法。 - 如果上游系统暴露了复选框和全局开关,最好在 UI 层就限制互斥选择。
4. 如何解决这个错误 #
常用修复思路 #
- 如果不想恢复任何 feature states,只传
none。 - 如果只想恢复部分 feature states,就删掉
none,仅保留具体名称。 - 在请求构造层加入互斥校验,禁止
none与其他值并存。 - 对自动化平台增加参数预览,避免错误组合进入生产。
后续注意事项与推荐建议 #
- 把
feature_states参数封装成明确的枚举模式,而不是裸数组拼接。 - 对 restore 工具链增加契约测试,覆盖
none和具体 feature 的组合场景。 - 文档里应明确写出
none的排他语义。
借助 INFINI 产品提升排障效率 #
- INFINI Console 适合查看集群健康度、节点指标、索引状态、错误趋势和请求画像,帮助快速判断异常是局部问题还是系统性问题。
- INFINI Gateway 适合部署在 Elasticsearch 前面做请求观测、限流、熔断、缓存和流量治理,尤其适合定位高频错误请求、异常重试和不合理 DSL。
- 如果需要长期治理,建议把异常日志、慢查询、调用来源和变更记录统一接入监控面板,缩短从“发现问题”到“定位根因”的时间。
5. 小结 #
这条错误的根因是 feature_states 参数自相矛盾。要么恢复 none,要么恢复具体 feature,不能同时两者都要。
相关错误 #
- 请求的功能状态 – 如何解决此 Elasticsearch 异常
- 请求的功能状态-featuresNotOnThisNode-存在于 - 如何解决此 Elasticsearch 异常
- failed-to-restore-snapshot-snapshotid-如何解决此Elasticsearch异常
附:日志上下文 #
下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题:
featureStatesToRestore = Collections.emptyMap();
} else {
// Otherwise; handle the list of requested feature states
final SetrequestedStates = org.elasticsearch.common.collect.Set.of(requestedFeatureStates);
if (requestedStates.contains(NO_FEATURE_STATES_VALUE)) {
throw new SnapshotRestoreException(snapshot; "the feature_states value [" + NO_FEATURE_STATES_VALUE +
"] indicates that no feature states should be restored; but other feature states were requested: " + requestedStates);
}
if (snapshotFeatureStates.keySet().containsAll(requestedStates) == false) {
SetnonExistingRequestedStates = new HashSet<>(requestedStates);
nonExistingRequestedStates.removeAll(snapshotFeatureStates.keySet());





