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

适用版本: 6.8-8.x

1. 错误说明 #

报错 failed to parse [<type>] action [<watch_id>/<action_id>]. failed to parse [fields] field 表示 Elasticsearch 在解析某个 action 的 fields 配置时失败了。

从附录代码可以看到,解析器直接调用 parser.map() 读取 fields。这意味着 fields 必须是一个标准 JSON 对象。如果这里给了字符串、数组、格式损坏的对象,或者对象内部存在无法解析的结构,就会抛出该异常。

2. 常见触发场景 #

  • fields 被写成字符串,例如把整段 JSON 当作文本传入。
  • fields 被写成数组,但解析逻辑期望的是键值对象。
  • 模板展开后生成了非法 JSON,导致 parser.map() 失败。

错误示例:

{
  "actions": {
    "notify": {
      "slack": {
        "fields": "severity=high"
      }
    }
  }
}

3. 排查方法 #

  1. 找出报错的具体 Watcher 和 action。
  2. 查看最终请求体中的 fields 是否为 JSON 对象,而不是字符串或数组。
  3. 如果 fields 来自模板生成,检查模板渲染结果是否仍然是合法对象。
  4. fields 单独抽出来做 JSON 校验,确认字段名和值都能被正常解析。

4. 修复方法 #

  • fields 改成标准对象结构。
  • 不要把对象序列化成字符串后再传给 fields
  • 对模板或程序化生成逻辑增加结构校验,确保输出始终是 map。

修正示例:

{
  "actions": {
    "notify": {
      "slack": {
        "fields": {
          "severity": "high",
          "service": "billing"
        }
      }
    }
  }
}

5. 预防建议 #

  • fields 这类对象字段建立固定的数据结构定义。
  • 在提交 Watcher 之前,对生成后的 JSON 做一次结构化校验。
  • 如果接入层允许用户自定义字段,先做白名单和类型限制。

相关错误 #

附:日志上下文 #

proxy = HttpProxy.parse(parser);
} else if (Field.FIELDS.match(currentFieldName; parser.getDeprecationHandler())) {
    try {
        fields = parser.map();
    } catch (Exception e) {
        throw new ElasticsearchParseException("failed to parse [{}] action [{}/{}]. failed to parse [{}] field"; e; TYPE;
            watchId; actionId; Field.FIELDS.getPreferredName());
    }
} else {
    throw new ElasticsearchParseException("failed to parse [{}] action [{}/{}]. unexpected token [{}/{}]"; TYPE; watchId;
        actionId; token; currentFieldName);