适用版本: 6.8-8.9
1. 错误异常的基本描述 #
could not parse week times. expected an object; but found [token] 是 Elasticsearch Watcher 定时任务调度配置中常见的解析异常。当 Elasticsearch 在解析 weekly 类型的 schedule(调度计划)时,期望 times 字段是一个 JSON 对象(Object),但实际解析到的却是一个字符串、数组或其他非对象类型,就会抛出此异常。
该异常通常发生在以下场景中:
- 创建或更新 Watcher 的 API 请求中,
trigger.schedule.times字段格式不正确。 - 从旧版本 Elasticsearch 迁移 Watcher 配置时,schedule 结构发生了变化但配置未同步更新。
- 通过脚本或自动化工具生成 Watcher 配置时,数据结构构造有误。
- 手动编辑 Watcher JSON 配置时,误将
times写成了字符串或数组而非对象。
常见现象 #
- 调用
_watcherAPI 创建或更新 watch 时,返回400 Bad Request错误。 - 响应体中包含
parse_exception类型的错误信息,提示could not parse week times. expected an object; but found [...]。 - Kibana 的 Watcher 管理界面可能无法保存配置,或显示校验错误。
- 已有的 Watcher 在集群升级后可能无法加载,导致定时任务失效。
典型报错与异常栈 #
实际报错信息通常类似下面这样:
{
"error": {
"root_cause": [
{
"type": "parse_exception",
"reason": "could not parse week times. expected an object; but found [VALUE_STRING]"
}
],
"type": "parse_exception",
"reason": "could not parse week times. expected an object; but found [VALUE_STRING]"
},
"status": 400
}
服务端日志中可能出现的异常栈:
ElasticsearchParseException: could not parse week times. expected an object; but found [VALUE_STRING]
at org.elasticsearch.xpack.watcher.trigger.schedule.WeekTimes.parse(WeekTimes.java)
at org.elasticsearch.xpack.watcher.trigger.schedule.WeeklySchedule$Parser.parse(WeeklySchedule.java)
at org.elasticsearch.xpack.watcher.trigger.schedule.ScheduleRegistry.parse(ScheduleRegistry.java)
2. 为什么会发生这个错误 #
WeekTimes.parse 是 Elasticsearch Watcher 中专门用于解析每周调度时间的方法。Weekly Schedule 的设计需要同时描述星期几和具体时间两个维度,因此其 times 配置必须是一个对象,才能完整表达这两个信息。
根本原因 #
WeekTimes.parse 方法的入口处会检查当前解析令牌(Token)类型,只有当令牌为 START_OBJECT 时才会继续解析,否则直接抛出 ElasticsearchParseException。这是因为:
- 对象结构才能承载完整信息:
weeklyschedule 的times需要同时指定星期(on)和具体时刻(at),只有对象才能同时包含这两个字段。 - 解析器无法推断单一值含义:如果
times只是一个字符串(如"12:00")或数组(如["12:00"]),解析器无法判断这是指星期几、具体时间,还是其他含义。 - 与 yearly schedule 类似的约束:
YearTimes.parse也有相同的约束,因为年度调度同样需要月份和日期两个维度。
常见错误写法 #
以下是几种常见的错误配置示例:
错误示例 1:将 times 写成字符串
{
"trigger": {
"schedule": {
"weekly": {
"times": "12:00"
}
}
}
}
错误示例 2:将 times 写成数组
{
"trigger": {
"schedule": {
"weekly": {
"times": ["12:00", "18:00"]
}
}
}
}
错误示例 3:遗漏 on 或 at 字段
{
"trigger": {
"schedule": {
"weekly": {
"times": {
"on": "monday"
}
}
}
}
}
3. 如何排查和解决这个异常 #
建议按以下步骤进行排查:
- 获取完整报错信息:查看 API 响应体或 Elasticsearch 日志,确认
token的具体类型(如VALUE_STRING、VALUE_ARRAY等),这能直接指出配置中times的实际类型。 - 检查 Watcher 配置:通过
_watcher/watch/{watch_id}API 获取当前 watch 的完整配置,重点检查trigger.schedule.weekly.times的结构。 - 对照正确格式:参考官方文档或本文的正确示例,确认
times是否为对象,且包含on和at两个字段。 - 检查配置来源:如果配置来自脚本、模板或迁移工具,追溯生成逻辑,定位数据构造错误的位置。
- 验证修复结果:修改配置后,先通过
_watcher/watch/{watch_id}/_executeAPI 手动触发一次,确认不再报错。
排查时需要注意的问题 #
weeklyschedule 的times与cronschedule 的语法完全不同,不要混淆两者。- 如果 Watcher 是从旧版本迁移过来的,注意 Elasticsearch 7.x 之后 Watcher 的 schedule 配置结构可能有变化。
on字段的值不区分大小写,但必须是有效的星期名称(monday、tuesday等),或使用数字0-6(0 表示星期日)。at字段的值必须是合法的 24 小时制时间字符串,格式为HH:mm或HH:mm:ss。
4. 如何解决这个错误 #
正确的配置格式 #
weekly schedule 的 times 必须是一个对象,包含 on(星期几)和 at(具体时间)两个字段:
正确示例 1:单个时间点
{
"trigger": {
"schedule": {
"weekly": {
"times": {
"on": "monday",
"at": "12:00"
}
}
}
}
}
正确示例 2:多个时间点(使用数组)
{
"trigger": {
"schedule": {
"weekly": {
"times": [
{
"on": "monday",
"at": "09:00"
},
{
"on": "friday",
"at": "17:00"
}
]
}
}
}
}
正确示例 3:使用数字表示星期
{
"trigger": {
"schedule": {
"weekly": {
"times": {
"on": 1,
"at": "08:30"
}
}
}
}
}
完整的 Watcher 创建示例 #
以下是一个完整的 Watcher 配置示例,每周一和周五的中午 12 点执行:
PUT _watcher/watch/weekly_report
{
"trigger": {
"schedule": {
"weekly": {
"times": [
{
"on": "monday",
"at": "12:00"
},
{
"on": "friday",
"at": "12:00"
}
]
}
}
},
"input": {
"search": {
"request": {
"indices": ["logs-*"],
"body": {
"query": {
"range": {
"@timestamp": {
"gte": "now-7d"
}
}
}
}
}
}
},
"condition": {
"compare": {
"ctx.payload.hits.total": {
"gt": 0
}
}
},
"actions": {
"send_email": {
"email": {
"to": ["admin@example.com"],
"subject": "Weekly Log Report",
"body": "Found {{ctx.payload.hits.total}} log entries in the past 7 days."
}
}
}
}
修复步骤 #
停止受影响的 Watcher(如果已存在):
POST _watcher/watch/{watch_id}/_deactivate更新配置,将
times修正为正确的对象格式:PUT _watcher/watch/{watch_id} { "trigger": { "schedule": { "weekly": { "times": { "on": "monday", "at": "12:00" } } } } }重新激活 Watcher:
POST _watcher/watch/{watch_id}/_activate手动执行验证:
POST _watcher/watch/{watch_id}/_execute
后续注意事项与推荐建议 #
- 在自动化生成 Watcher 配置时,加入 JSON Schema 校验,确保
times字段结构正确后再提交到 Elasticsearch。 - 对于复杂的调度需求,考虑使用
cronschedule 替代weekly,cron表达式更灵活且不易出错:{ "trigger": { "schedule": { "cron": "0 12 * * 1,5" } } } - 建立 Watcher 配置的版本管理机制,所有变更都经过测试环境验证后再应用到生产环境。
- 定期检查 Watcher 的执行状态,通过
_watcher/statsAPI 监控是否有失败的 watch。
借助 INFINI 产品提升排障效率 #
- INFINI Console 适合查看集群健康度、索引状态、错误趋势和请求画像,帮助快速判断 Watcher 相关异常是配置问题还是集群问题。
- INFINI Gateway 适合部署在 Elasticsearch 前面做请求观测、限流和流量治理,可以帮助捕获 Watcher API 的异常请求,便于排查配置错误。
- 建议将 Watcher 执行日志、错误信息和变更记录统一接入监控面板,缩短从"发现问题"到"定位根因"的时间。
5. 小结 #
could not parse week times. expected an object; but found [...] 的核心原因是 weekly schedule 的 times 配置格式不正确——解析器期望一个对象(Object),却收到了其他类型的数据。只要确保 times 是一个包含 on(星期)和 at(时间)字段的对象,问题即可解决。
处理这类异常时,最有效的方法是先通过报错信息确认 times 的实际类型,再对照正确格式修正配置。对于需要复杂调度逻辑的场景,也可以考虑使用 cron schedule 替代 weekly,以减少配置错误的可能性。
相关错误 #
附:日志上下文 #
下面保留当前页面中的源码片段,便于结合异常调用栈定位问题:
public static WeekTimes parse(XContentParser parser, XContentParser.Token token) throws IOException, ElasticsearchParseException {
if (token != XContentParser.Token.START_OBJECT) {
throw new ElasticsearchParseException("could not parse week times. expected an object; but found [{}]", token);
}
// ... 继续解析 on 和 at 字段
}





