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

适用版本: 7.2-7.15

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

analyzer [xxx] contains filters [yyy] that are not allowed to run in [mode] mode 是 Elasticsearch 在索引映射(mapping)或索引模板中配置自定义分析器时抛出的异常。该错误的核心含义是:分析器中引用了不允许在当前分析模式下运行的 token filter

Elasticsearch 从 7.x 开始对分析器的运行模式(AnalysisMode)进行了严格区分,某些 token filter 只能在特定模式下运行(如索引时 INDEX 模式或搜索时 SEARCH 模式)。当分析器配置中混入了不匹配的过滤器时,就会触发此异常。

常见现象 #

  • 创建索引、更新映射或应用索引模板时,Elasticsearch 返回 HTTP 400 Bad Request,并附带 MapperException 异常信息。
  • 集群日志中出现类似以下报错:
MapperException: analyzer [my_analyzer] contains filters [synonym, keyword_repeat]
that are not allowed to run in index mode.
  • 索引创建失败,导致依赖该索引的数据写入任务全部报错,影响业务正常运行。
  • 如果使用动态模板或索引生命周期管理(ILM),相关索引滚动操作也会失败。

典型报错与异常栈 #

org.elasticsearch.index.mapper.MapperException: analyzer [my_analyzer] contains filters
[synonym] that are not allowed to run in index mode.
    at org.elasticsearch.index.analysis.CustomAnalyzer.checkAnalysisMode(CustomAnalyzer.java)
    at org.elasticsearch.index.analysis.CustomAnalyzer.build(CustomAnalyzer.java)
    at org.elasticsearch.index.analysis.AnalysisRegistry.buildCustomAnalyzer(AnalysisRegistry.java)

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

Elasticsearch 的 token filter 分为三种运行模式,由 AnalysisMode 枚举定义:

模式说明典型 filter 示例
INDEX仅允许在索引写入阶段运行trimlowercaseasciifolding
SEARCH仅允许在搜索分析阶段运行synonym(搜索时同义词)、keyword_repeat
ALL索引和搜索阶段均可运行standardicu_normalizer

当自定义分析器引用了 AnalysisMode 与当前使用场景不匹配的 filter 时,就会触发此异常。常见原因包括:

  • 混淆了索引分析与搜索分析的职责:将只能在搜索时使用的 filter(如 synonym 的搜索变体)配置到了索引分析器中。
  • 直接复制了示例配置但未理解模式限制:从官方文档或社区复制的分析器配置,其 filter 列表在当前版本中已被限制运行模式。
  • 插件提供的 filter 模式不兼容:第三方分析插件(如 ICU、SmartCN、IK)升级后,某些 filter 的 AnalysisMode 发生了变更。
  • 索引分析器与搜索分析器配置不对称analyzersearch_analyzer 各自引用了不合规的 filter 组合。

3. 如何排查这个异常 #

建议按以下顺序定位问题根因:

3.1 提取完整报错信息 #

首先从 Elasticsearch 日志或 API 响应中提取完整的异常信息,重点关注:

  • 分析器名称(analyzer [xxx]
  • offending filter 列表(contains filters [yyy]
  • 当前模式(not allowed to run in [mode] mode

3.2 检查索引映射或模板配置 #

使用以下 API 查看当前生效的分析器配置:

# 查看索引的 mapping 设置
GET /your_index/_settings

# 查看索引模板
GET /_index_template/your_template

# 查看组件模板(如果使用了可组合模板)
GET /_component_template/your_component_template

重点检查 settings.analysis.analyzer.<analyzer_name>.filter 字段,列出所有引用的 filter 名称。

3.3 验证每个 filter 的运行模式 #

通过 _analysis/analyze API 或查阅官方文档,确认每个 filter 支持的 AnalysisMode

# 测试 filter 是否在当前模式下可用
POST /_analyze
{
  "analyzer": "your_analyzer_name",
  "text": "测试文本"
}

如果返回同样的异常,则说明分析器配置本身有问题。

4. 如何解决这个错误 #

4.1 移除不合规的 filter #

最直接的修复方式是:从分析器的 filter 列表中移除报错的 filter,或将其替换为同样功能但支持当前模式的替代 filter。

修复前(错误配置):

{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": ["lowercase", "synonym"]
        }
      }
    }
  }
}

修复后(正确配置):

{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_index_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": ["lowercase"]
        },
        "my_search_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": ["lowercase", "synonym"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "content": {
        "type": "text",
        "analyzer": "my_index_analyzer",
        "search_analyzer": "my_search_analyzer"
      }
    }
  }
}

4.2 为索引和搜索分别配置分析器 #

如果某个 filter 只能在搜索时使用(如搜索时同义词),正确的做法是为字段分别设置 analyzer(索引时)和 search_analyzer(搜索时),如上方示例所示。

4.3 重建已受影响的索引 #

如果索引已经创建失败,需要先清理再重建:

# 删除创建失败的索引
DELETE /your_index

# 修正 settings 后重新创建
PUT /your_index
{
  "settings": { ... },
  "mappings": { ... }
}

5. 如何预防此类问题 #

配置规范建议 #

  • 索引/搜索职责分离:始终为复杂的分析需求分别定义 analyzersearch_analyzer,避免将所有 filter 堆砌在同一个分析器中。
  • 在测试环境验证:任何自定义分析器配置在应用到生产环境前,必须先在测试环境通过 _analyze API 验证。
  • 显式声明 filter 顺序:filter 的执行顺序影响分析结果,在配置中显式列出并注释每个 filter 的用途,便于后续维护。

版本升级注意事项 #

  • 从 6.x 升级到 7.x 时,AnalysisMode 的校验逻辑被引入,此前能正常工作的分析器配置可能在升级后报错。升级前务必在测试环境全量验证自定义分析器配置。
  • 第三方分析插件(IK、SmartCN、ICU 等)升级后,建议查阅其 Release Notes 中关于 AnalysisMode 的变更说明。

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

  • INFINI Console 适合查看集群健康度、索引配置、分析器设置及错误趋势,帮助快速判断异常是配置问题还是运行时问题。
  • INFINI Gateway 适合部署在 Elasticsearch 前面做请求观测、限流与缓存,在索引创建失败的场景下可以快速定位是哪个请求体触发了异常,并支持对高频失败请求进行熔断保护。

7. 小结 #

analyzer name contains filters that are not allowed to run in [mode] mode 的本质是分析器配置中引用了与当前运行模式不兼容的 token filter。通过理解 AnalysisMode 的三种模式(INDEX / SEARCH / ALL),并将索引分析与搜索分析的职责明确分离,可以从根本上避免此类问题。

建议在分析器配置变更时,始终通过 _analyze API 进行验证,并结合 INFINI Console 和 INFINI Gateway 建立持续的可观测性,缩短从发现问题到定位根因的时间。

相关错误 #

附:日志上下文 #

以下为 Elasticsearch 源码中抛出此异常的相关逻辑,便于深入理解触发条件:

AnalysisMode filterMode = tokenFilter.getAnalysisMode();
if (filterMode != AnalysisMode.ALL && filterMode != mode) {
    offendingFilters.add(tokenFilter.name());
}
}
throw new MapperException("analyzer [" + name + "] contains filters " + offendingFilters
    + " that are not allowed to run in " + mode.getReadableName() + " mode.");
} else {
    throw new MapperException(
        "analyzer [" + name + "] contains components that are not allowed to run in "
        + mode.getReadableName() + " mode.");
}