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

适用版本: 7.4-8.9

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

Attempted to start a failed transform 表示尝试启动一个已经处于 FAILED 状态的 Transform 任务。Elasticsearch 的 Transform 任务在运行失败后会进入 failed 状态,此时不允许直接再次启动,必须先处理失败原因并将任务重置为可启动状态,否则会抛出此异常。

常见现象 #

  • 调用 _transform/<transform_id>/_start API 时返回 400500 状态码,响应体中包含 Attempted to start a failed transform 错误信息。
  • Transform 任务在监控面板中显示为红色或失败状态,且无法通过界面或 API 重新启动。
  • 在 Elasticsearch 日志中可以看到类似 attempted to start while failed 的日志记录。
  • 依赖该 Transform 输出索引的下游查询或仪表盘可能无法获取最新数据。

典型报错与异常栈 #

{
  "error": {
    "root_cause": [
      {
        "type": "elasticsearch_exception",
        "reason": "Attempted to start a failed transform [my_transform]"
      }
    ],
    "type": "elasticsearch_exception",
    "reason": "Attempted to start a failed transform [my_transform]"
  },
  "status": 400
}

服务端日志中常见的异常栈片段:

ElasticsearchException[Attempted to start a failed transform [my_transform]]
    at org.elasticsearch.xpack.transform.TransformTask.onStart(TransformTask.java)
    at org.elasticsearch.xpack.transform.action.TransportStartTransformAction$1.onFailure(TransportStartTransformAction.java)

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

Transform 任务在执行过程中如果遇到不可恢复的错误,会自动将自身状态设置为 failed。常见触发原因包括:

  • 源索引不存在或 mapping 发生变更:Transform 依赖的源索引被删除,或关键字段的 mapping 发生变化(如字段类型变更、字段被删除),导致持续查询失败。
  • 目标索引写入失败:目标索引设置了严格的 mapping 限制、磁盘空间不足、或索引处于只读状态,导致 Transform 无法写入结果数据。
  • 脚本执行错误:Transform 配置中使用了 Painless 脚本,而脚本中存在空指针访问、类型不匹配或除零等运行时错误。
  • 资源不足:Transform 运行期间集群出现内存压力、线程池满载或长时间 GC,导致任务被中断并标记为失败。
  • 集群重启或节点异常退出:Transform 任务所在的节点异常下线,且任务无法在其它节点上正确恢复。

3. 如何排查这个异常 #

建议按以下步骤定位根因:

  1. 查看 Transform 任务详情:调用 GET _transform/<transform_id>/_stats 获取任务的详细状态、失败原因和运行历史。
  2. 查看任务失败原因:调用 GET _transform/<transform_id> 查看任务配置,同时检查 failure_reason 字段(如果有记录)。
  3. 检查源索引状态:确认源索引是否存在、是否健康、mapping 是否与 Transform 查询条件兼容。
  4. 检查目标索引状态:确认目标索引是否存在、是否可写、磁盘空间是否充足。
  5. 查看 Elasticsearch 日志:在任务失败时间点的附近搜索 transform 关键字,查找具体的异常堆栈。

排查示例命令 #

# 查看 Transform 任务状态
GET _transform/my_transform/_stats

# 查看 Transform 配置
GET _transform/my_transform

# 查看最近的 Transform 审计日志
GET _cluster/settings?include_defaults=true

4. 如何解决这个错误 #

步骤一:确认失败原因并修复根本问题 #

根据第 3 步的排查结果,先修复导致 Transform 失败的根本问题。例如:

  • 如果是源索引 mapping 变更导致,需要更新 Transform 配置以适配新的 mapping;
  • 如果是目标索引磁盘空间不足,需要清理磁盘或扩容;
  • 如果是脚本错误,需要修正 Painless 脚本逻辑。

步骤二:重置 Transform 任务状态 #

修复根本原因后,需要将 Transform 任务从 failed 状态重置。Transform 中没有直接的「重置」API,但可以通过以下方式实现:

# 方式一:先停止(如果任务仍在 failed 状态,stop 通常可以执行),再重新启动
POST _transform/my_transform/_stop
POST _transform/my_transform/_start

如果 stop 也无法执行,可以尝试:

# 方式二:删除并重建 Transform(会保留已生成的数据)
DELETE _transform/my_transform
# 重新创建 Transform
PUT _transform/my_transform
{
  "source": { ... },
  "dest": { ... },
  "pivot": { ... }
}
POST _transform/my_transform/_start

步骤三:验证任务恢复正常运行 #

# 确认任务状态变为 started
GET _transform/my_transform/_stats

5. 如何预防此类问题 #

最佳实践建议 #

  • 为 Transform 源索引设置索引生命周期管理(ILM):确保源索引不会被意外删除,且 mapping 变更时有明确的兼容性策略。
  • 为 Transform 目标索引预留充足的磁盘空间:设置磁盘水位线告警,避免因磁盘满导致写入失败。
  • 在 Transform 配置中使用脚本时增加空值保护:Painless 脚本中应显式处理可能为 null 的字段,避免运行时异常。
  • 启用 Transform 健康检查:定期通过 _transform/_stats 监控所有 Transform 任务的状态,及时发现 failed 状态的任务。
  • 在低峰期执行 Transform 变更操作:修改 Transform 配置或 mapping 时,尽量避开业务高峰,并在测试环境充分验证。

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

  • INFINI Console 适合查看集群健康度、Transform 任务状态、索引状态和错误趋势,帮助快速判断任务失败是数据问题、资源问题还是配置问题。
  • INFINI Gateway 适合部署在 Elasticsearch 前面做请求观测、限流和流量治理,可有效监控 Transform 相关的查询和写入请求,及时发现异常模式。
  • 建议将 Transform 任务状态、失败事件和索引变更记录统一接入监控面板,建立从「任务异常」到「根因定位」的快速响应机制。

6. 小结 #

Attempted to start a failed transform 异常的核心原因是 Transform 任务处于失败状态,不允许直接重启。处理此类问题的关键是:先查失败原因,再修根本原因,最后重置任务状态。通过建立 Transform 健康监控、合理配置资源预留和脚本防护,可以有效降低此类问题的发生频率。

相关错误 #

附:日志上下文 #

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

@Override
protected void onStart(long now, ActionListener<Void> listener) {
    if (context.getTaskState() == TransformTaskState.FAILED) {
        logger.debug("[{}] attempted to start while failed.", getJobId());
        listener.onFailure(new ElasticsearchException(
            "Attempted to start a failed transform [{}].", getJobId()));
        return;
    }
    // ...
}