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

适用版本: 6.8-8.11

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

invalid time minute value. expected string/number value or an array of string/number values; but found [token] 是 Elasticsearch Watcher 功能在解析定时触发器(schedule trigger)中的 minute 字段时抛出的异常。

该错误表明 minute 配置的顶层结构不符合 Watcher 调度器的预期格式。Watcher 的 cron 风格时间配置只允许两种合法形态:

  • 单个值:整数或字符串形式的分钟数,如 15"15"
  • 数组:由整数或字符串分钟数组成的数组,如 [15, 30, 45]

一旦解析器在顶层遇到对象({})、布尔值(true/false)、null 或其他非预期类型,就会在展开数组之前直接抛出异常,导致整个 Watcher 无法注册或更新。

常见现象 #

  • 调用 _watcher API 创建或更新 Watch 时,Elasticsearch 返回 400 Bad Request,响应体中包含上述异常信息。
  • Kibana 的 Watcher 管理界面可能提示"Failed to create watch"或"Invalid schedule configuration"。
  • 已有的 Watch 在集群升级或配置热更新时可能因格式问题而加载失败,导致定时任务不再触发。
  • 开发或运维人员在 Dev Tools 中执行 PUT 请求时,立即收到解析错误,无法直接保存配置。

典型报错与异常栈 #

报错通常出现在以下场景的响应中:

{
  "error": {
    "root_cause": [
      {
        "type": "elasticsearch_parse_exception",
        "reason": "invalid time minute value. expected string/number value or an array of string/number values; but found [START_OBJECT]"
      }
    ],
    "type": "elasticsearch_parse_exception",
    "reason": "invalid time minute value. expected string/number value or an array of string/number values; but found [START_OBJECT]"
  },
  "status": 400
}

服务端日志中可能出现类似下面的异常栈:

org.elasticsearch.common.ParsingException: invalid time minute value. expected string/number value or an array of string/number values; but found [START_OBJECT]
    at org.elasticsearch.xpack.watcher.trigger.schedule.ScheduleTrigger.parseSchedule(ScheduleTrigger.java:...)
    at org.elasticsearch.xpack.watcher.watch.WatchParser.parseTrigger(WatchParser.java:...)
    ...

ElasticsearchParseExceptionillegal_argument_exceptionparse_exception 等关键字可能会与该错误同时出现,具体返回内容会因接口、版本与上下文而变化。

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

Watcher 的 schedule 配置中,minute 字段用于指定每小时内的哪些分钟触发执行。Elasticsearch 在解析该字段时,期望的 JSON 结构非常严格。

源码层面的约束 #

从 Elasticsearch 源码来看,minute 的解析逻辑大致如下:

  1. 读取当前 JSON token。
  2. 如果是数值(VALUE_NUMBER)或字符串(VALUE_STRING),按单个分钟值处理。
  3. 如果是数组起始(START_ARRAY),则遍历数组内的每个元素,要求每个元素都是数值或字符串。
  4. 如果以上都不匹配(例如遇到了 START_OBJECTVALUE_BOOLEANVALUE_NULL 等),则直接抛出 ElasticsearchParseException,并提示 invalid time minute value...

常见错误原因 #

  • 误将 minute 写成对象:例如 {"minute": {"from": 0, "to": 59}}{"minute": {"values": [0, 15, 30, 45]}},这是把 minute 本身定义成了对象,而非预期的单值或数组。
  • 误用 cron 表达式字符串:例如 "minute": "*/15",cron 表达式应写在 cron 字段中,而非 minute 字段。
  • 模板渲染错误:使用外部模板引擎(如 Jinja2、Mustache)生成 Watch JSON 时,变量替换后产生了非预期的结构,例如 {{ minute_config }} 渲染成了一个对象而非数组。
  • 布尔值或 null 误入:例如 "minute": true"minute": null,通常来自动态配置中条件分支的遗漏处理。
  • 多层嵌套数组:例如 "minute": [[15, 30]],嵌套数组不符合解析器的预期,会直接报错。
  • 从旧版本迁移时配置格式不兼容:某些早期版本的 Watcher 配置写法在新版本中不再被支持。

3. 如何排查和解决这个异常 #

建议按"先定位错误位置,再确认配置结构,最后修复并验证"的顺序处理:

排查步骤 #

  1. 获取完整报错信息:从 Elasticsearch 响应或日志中找到完整的异常信息,确认 but found [...] 中的 token 类型,这能直接提示是哪种结构错了。
  2. 定位 Watch 配置:找到触发报错的 Watch ID,通过 GET _watcher/watch/<watch_id> 获取完整配置,重点检查 trigger.schedule 下的 minute 字段。
  3. 检查 JSON 结构:确认 minute 字段的顶层是数值、字符串还是数组,是否存在多余的对象包装。
  4. 回溯配置来源:如果 Watch 是通过脚本或模板生成的,检查生成逻辑是否正确输出了数组或单值,而非对象。
  5. 验证修复结果:修复后使用 PUT _watcher/watch/<watch_id> 重新提交,确认不再报错,并通过 GET _watcher/watch/<watch_id>/_status 确认 Watch 已正常加载。

排查时需要注意的问题 #

  • 不要只看报错表面的 minute,有时 hourdaymonth 等字段也会出现类似的解析错误,需要一并检查整个 schedule 配置块。
  • 如果 Watch 是通过 Kibana 界面创建的,注意界面上的"高级配置"模式可能允许输入任意 JSON,容易出现格式错误。
  • 使用动态模板生成 Watch 时,务必在模板渲染后打印最终 JSON,确认结构符合预期,再提交到 Elasticsearch。

4. 如何解决这个错误 #

常用修复思路 #

修复方式一:将对象改为单值或数组 #

错误写法(对象形式):

{
  "trigger": {
    "schedule": {
      "minute": { "values": [15, 30, 45] }
    }
  }
}

正确写法(数组形式):

{
  "trigger": {
    "schedule": {
      "minute": [15, 30, 45]
    }
  }
}

正确写法(单值形式):

{
  "trigger": {
    "schedule": {
      "minute": 30
    }
  }
}

修复方式二:将 cron 表达式移到正确字段 #

错误写法(在 minute 中使用 cron 表达式):

{
  "trigger": {
    "schedule": {
      "minute": "*/15"
    }
  }
}

正确写法(使用 cron 字段):

{
  "trigger": {
    "schedule": {
      "cron": "*/15 * * * *"
    }
  }
}

修复方式三:修复模板渲染逻辑 #

如果 Watch 是通过模板生成的,确保模板输出符合预期。例如使用 Jinja2 时:

错误的模板(可能输出对象):

"minute": {{ minute_config }}

如果 minute_config 是一个对象 {"values": [15, 30]},渲染后就会出错。

正确的模板(确保输出数组):

"minute": [{{ minute_values | join(', ') }}]

其中 minute_values 是一个数组变量,如 [15, 30, 45]

修复方式四:使用 Dev Tools 验证完整配置 #

在 Kibana Dev Tools 中验证一个完整的 Watch 配置:

PUT _watcher/watch/my_watch
{
  "trigger": {
    "schedule": {
      "minute": [0, 15, 30, 45],
      "hour": "*"
    }
  },
  "input": {
    "search": {
      "request": {
        "indices": ["my-index"],
        "body": {
          "query": { "match_all": {} }
        }
      }
    }
  },
  "condition": {
    "compare": {
      "ctx.payload.hits.total": { "gt": 0 }
    }
  },
  "actions": {
    "log": {
      "logging": {
        "text": "Found {{ctx.payload.hits.total}} hits"
      }
    }
  }
}

提交后确认返回 "acknowledged": true,再通过以下命令验证 Watch 状态:

GET _watcher/watch/my_watch/_status

后续注意事项与推荐建议 #

  • 在 CI/CD 流程中加入 Watch JSON 的 schema 校验步骤,在提交前就发现格式问题,避免将错误配置推到生产环境。
  • 对于复杂的定时需求,优先考虑使用 cron 表达式而非单独的 minute/hour/day 字段组合,可读性和维护性更好。
  • 建立 Watch 配置的版本管理机制,每次变更都有 diff 记录,便于快速回滚到上一个可用版本。
  • 在测试环境充分验证 Watch 配置后再应用到生产,尤其注意 minute 值范围是 0-59,超出范围会触发另一个异常(可参考相关错误链接)。

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

  • INFINI Console 适合查看集群健康度、节点指标、索引状态,并可通过其界面化管理能力辅助观察 Watcher 执行情况,帮助快速判断定时任务是否按预期触发。
  • INFINI Gateway 适合部署在 Elasticsearch 前面做请求观测、限流和流量治理,可以在 Watcher 触发大量操作时提供额外的可观测性支持,避免批量操作对集群造成冲击。
  • 建议将 Watch 执行日志、失败记录和变更历史统一接入监控面板,缩短从"发现定时任务未执行"到"定位配置错误"的时间。

5. 小结 #

invalid time minute value. expected string/number value or an array of string/number values 这个错误的根因非常明确:Watcher scheduleminute 字段的顶层结构不符合解析器的预期。修复的核心思路是:

  1. 确认 minute 字段是单个数值/字符串,或是由数值/字符串组成的数组;
  2. 不要将 minute 本身定义为对象;
  3. 如果需求是 cron 表达式,应使用 cron 字段而非 minute 字段。

只要遵循 Watcher 调度配置的正确 JSON 结构,并在模板生成或动态配置场景中做好输出校验,这类问题完全可以提前规避。对于已经出现的错误,结合完整的报错 token 信息和 Watch 配置,通常可以在几分钟内定位并修复。

相关错误 #

附:日志上下文 #

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

} else {
    throw new ElasticsearchParseException("invalid time minute value. expected string/number value or an array of " +
        "string/number values; but found [{}]", token);
}