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

适用版本: 6.8-8.9

1. 错误说明 #

Failed to build aggregation [aggregator_name] 表示 Elasticsearch 在执行完聚合计算后、准备将结果写入响应时发生了异常。该错误并非发生在 DSL 解析或查询执行阶段,而是在结果构造阶段(buildTopLevel)抛出的,因此排查思路与普通查询错误有所不同。

常见现象 #

  • 聚合请求返回 500503 状态码,响应体中包含 Failed to build aggregation 错误信息。
  • 部分聚合可以正常返回,但某个特定聚合器在结果构造阶段失败,导致整个响应中断。
  • 在 Elasticsearch 服务端日志中可以看到 AggregationExecutionException,并附带具体聚合器名称。
  • 如果使用了多层嵌套聚合或 pipeline 聚合,错误可能只在特定数据条件下触发,难以稳定复现。

典型报错 #

{
  "error": {
    "root_cause": [
      {
        "type": "aggregation_execution_exception",
        "reason": "Failed to build aggregation [my_agg]"
      }
    ],
    "type": "search_phase_execution_exception",
    "reason": "all shards failed",
    "failed_shards": [
      {
        "reason": {
          "type": "aggregation_execution_exception",
          "reason": "Failed to build aggregation [my_agg]",
          "caused_by": {
            "type": "io_exception",
            "reason": "No space left on device"
          }
        }
      }
    ]
  }
}

2. 原因分析 #

从 Elasticsearch 源码来看,聚合结果构建的核心逻辑位于 SearchPhaseController 中,在聚合执行完成后遍历所有聚合器并调用 buildTopLevel()

for (Aggregator aggregator : context.aggregations().aggregators()) {
    try {
        aggregator.postCollection();
        aggregations.add(aggregator.buildTopLevel());
    } catch (IOException e) {
        throw new AggregationExecutionException(
            "Failed to build aggregation [" + aggregator.name() + "]", e);
    }
    aggregator.releaseAggregations();
}

常见触发原因包括:

  • 聚合器内部状态不完整:聚合执行过程中累计的中间状态因异常数据而损坏,导致无法正确生成顶层结果对象。
  • 字段映射或数据类型异常:聚合所依赖的字段 mapping 发生变化(如字段类型变更、doc values 被禁用),而已有数据与新 mapping 不兼容。
  • 脚本或 runtime field 错误:在聚合中使用了脚本或 runtime field,脚本逻辑在序列化阶段抛出 IOExceptionClassCastException
  • 插件型聚合器兼容性问题:使用了第三方插件提供的聚合类型,插件版本与当前 Elasticsearch 版本不兼容,在结果序列化时失败。
  • 嵌套或 pipeline 聚合层级过深:多层嵌套聚合或连续 pipeline 聚合(如 bucket_sortcumulative_sum)在中间桶数据为空或格式异常时,下游聚合在构建结果时失败。
  • 磁盘空间不足或 IO 异常buildTopLevel() 阶段可能涉及中间文件写入或网络 IO,若磁盘满或发生 IO 错误,会被包装成当前异常。

3. 解决方案 #

3.1 定位具体聚合器 #

首先从异常信息中提取聚合器名称,将原始 DSL 逐步精简,使用最小可复现的聚合定义进行隔离测试:

{
  "size": 0,
  "aggs": {
    "problem_agg": {
      "terms": {
        "field": "your_field.keyword",
        "size": 10
      }
    }
  }
}

3.2 检查字段 mapping 与数据兼容性 #

使用以下步骤确认字段状态:

# 查看索引 mapping
GET /your_index/_mapping/field/your_field

# 查看字段是否存在 doc_values 被禁用的情况
GET /your_index/_mapping

# 检查是否有 runtime field 定义冲突
GET /your_index/_mapping?include_runtime=true

3.3 修复脚本或 runtime field #

如果聚合依赖脚本,验证脚本逻辑:

{
  "size": 0,
  "runtime_mappings": {
    "test_script_field": {
      "type": "long",
      "script": {
        "source": "emit(doc['price'].value ?: 0)"
      }
    }
  },
  "aggs": {
    "test_agg": {
      "terms": {
        "field": "test_script_field"
      }
    }
  }
}

3.4 处理嵌套或 pipeline 聚合 #

逐层拆解复杂聚合,定位具体失败层级:

{
  "size": 0,
  "aggs": {
    "level1": {
      "terms": {
        "field": "category.keyword"
      },
      "aggs": {
        "level2": {
          "avg": {
            "field": "price"
          }
        }
      }
    }
  }
}

先去掉 level2,确认 level1 是否正常;再逐步加回下游聚合,直到错误复现。

3.5 检查节点磁盘与 IO 状态 #

# 检查磁盘使用率
GET /_cat/allocation?v

# 检查节点信息
GET /_cat/nodes?v&h=name,disk.avail,disk.total,disk.percent

4. 预防措施 #

  • 变更字段 mapping 前做好兼容性评估:避免直接修改已有字段类型,优先使用别名或新增字段的方式平滑迁移。
  • 脚本和 runtime field 上线前充分测试:在开发或测试环境验证脚本逻辑对边界数据(null、空字符串、异常类型)的处理能力。
  • 控制聚合复杂度:避免过深的嵌套聚合层级和过多的 bucket 数量,必要时使用 composite 聚合替代深度嵌套。
  • 监控磁盘使用率与 IO 异常:建立磁盘水位告警,避免因磁盘满导致聚合结果写入失败。
  • 定期巡检插件兼容性:升级 Elasticsearch 版本时同步确认第三方插件是否提供对应版本的兼容包。

5. 相关错误 #

附:日志上下文 #

for (Aggregator aggregator : context.aggregations().aggregators()) {
    try {
        aggregator.postCollection();
        aggregations.add(aggregator.buildTopLevel());
    } catch (IOException e) {
        throw new AggregationExecutionException(
            "Failed to build aggregation [" + aggregator.name() + "]", e);
    }
    // release the aggregator to claim the used bytes as we don't need it anymore
    aggregator.releaseAggregations();
}
context.queryResult().aggregations(InternalAggregations.from(aggregations));