--- title: "could not parse month times expected an object but found - 如何解决此 Elasticsearch 异常" date: 2026-03-19 lastmod: 2026-03-19 description: "could not parse month times expected an object but found 表示 monthly schedule 的 times 配置不是对象结构,通常由于 JSON 结构错误或模板渲染问题导致。" tags: ["Watcher", "month schedule", "times", "parse_exception", "定时调度", "monthly schedule"] summary: "适用版本: 6.8-8.9 1. 错误异常的基本描述 # could not parse month times. expected an object; but found [token] 是 Elasticsearch Watcher 在解析 monthly schedule(月度调度)配置时抛出的异常。当 times 字段的值不是解析器期望的对象结构时,就会触发此错误。 monthly schedule 需要描述月份中的第几天和具体时间,因此 times 必须是包含 day 和 time 等子字段的对象,不能是简单的字符串或数字。 常见现象 # 创建或更新 watch 时返回 HTTP 400 错误。 报错信息明确指出实际找到的 token 类型(如 VALUE_STRING、VALUE_NUMBER 等)。 常见于手动编写复杂的 monthly schedule 配置时,或在使用模板生成配置时。 如果配置由 UI 或模板自动生成,可能出现对象被序列化为字符串的问题。 典型报错与异常栈 # { "error": { "root_cause": [ { "type": "parse_exception", "reason": "could not parse month times." --- > **适用版本:** 6.8-8.9 ## 1. 错误异常的基本描述 `could not parse month times. expected an object; but found [token]` 是 Elasticsearch Watcher 在解析 monthly schedule(月度调度)配置时抛出的异常。当 `times` 字段的值不是解析器期望的对象结构时,就会触发此错误。 monthly schedule 需要描述月份中的第几天和具体时间,因此 `times` 必须是包含 `day` 和 `time` 等子字段的对象,不能是简单的字符串或数字。 ### 常见现象 - 创建或更新 watch 时返回 HTTP 400 错误。 - 报错信息明确指出实际找到的 token 类型(如 `VALUE_STRING`、`VALUE_NUMBER` 等)。 - 常见于手动编写复杂的 monthly schedule 配置时,或在使用模板生成配置时。 - 如果配置由 UI 或模板自动生成,可能出现对象被序列化为字符串的问题。 ### 典型报错与异常栈 ```json { "error": { "root_cause": [ { "type": "parse_exception", "reason": "could not parse month times. expected an object; but found [VALUE_STRING]" } ], "type": "parse_exception", "reason": "could not parse month times. expected an object; but found [VALUE_STRING]" }, "status": 400 } ``` 服务端日志中可能出现类似以下内容: ```text [2024-01-15T10:30:00,123][WARN ][o.e.x.w.s.MonthTimes ] [node-1] failed to parse month times ElasticsearchParseException[could not parse month times. expected an object; but found [VALUE_STRING]] at org.elasticsearch.xpack.watcher.trigger.schedule.MonthTimes.parse(MonthTimes.java:67) at org.elasticsearch.xpack.watcher.trigger.schedule.MonthlySchedule.parse(MonthlySchedule.java:89) ``` ## 2. 为什么会发生这个错误 `MonthTimes.parse` 方法期望 `times` 字段的值是一个 JSON 对象(`START_OBJECT` token)。如果传入的是其他类型(如字符串、数字、数组等),就会抛出此异常。 常见原因包括: - **JSON 结构错误**:`times` 被写成了字符串或数字,而不是对象。例如:`"times": "1st"` 应该是 `"times": {"day": 1, "time": "12:00"}`。 - **模板渲染问题**:使用 Mustache 或 script 模板时,渲染结果可能不是合法的对象结构。 - **序列化问题**:如果配置由程序自动生成,序列化过程可能把对象压扁成了字符串。 - **复制粘贴错误**:从其他配置复制时,可能遗漏了对象的大括号 `{}`。 - **字段类型混淆**:把应该是对象的字段写成了数组或字符串。 - **版本差异**:不同版本的 Watcher 对 `times` 结构的要求可能不同。 ## 3. 如何排查和解决这个异常和解决这个异常 ### 排查步骤 1. **确认报错信息中的 token 类型**:从错误信息中提取实际找到的 token 类型(`found [token]`),判断是字符串、数字还是其他类型。 2. **检查 Watch 中的 monthly schedule 配置**: ```bash # 获取 watch 配置 GET _watcher/watch/?pretty # 检查 trigger 部分的 monthly schedule ``` 3. **验证 `times` 字段的结构**:确认 `times` 是对象类型,且包含必需的子字段。 ```bash # 正确的 monthly schedule 结构示例 PUT _watcher/watch/ { "trigger": { "schedule": { "monthly": { "times": [ { "day": 1, "time": "12:00" }, { "day": 15, "time": "18:00" } ] } } }, ... } ``` 4. **检查模板渲染结果**:如果使用动态模板,先渲染模板确认结果是否是合法的对象结构。 ### 排查时需要注意的问题 - 注意 `times` 是一个数组,数组中的每个元素都是对象(包含 `day` 和 `time` 字段)。 - 如果使用了模板变量,确保变量渲染后不会产生字符串或其他非对象类型。 - 检查 JSON 格式是否正确,特别是对象的大括号 `{}` 是否配对。 ## 4. 如何解决这个错误 ### 常用修复思路 1. **恢复 `times` 的对象结构**:确保 `times` 是包含 `day` 和 `time` 字段的对象数组。 ```bash # 修复前(错误:times 是字符串) PUT _watcher/watch/ { "trigger": { "schedule": { "monthly": { "times": "1st day at 12:00" # 错误 } } } } # 修复后(正确:times 是对象数组) PUT _watcher/watch/ { "trigger": { "schedule": { "monthly": { "times": [ { "day": 1, "time": "12:00" } ] } } } } ``` 2. **使用最小样板验证**:先用最简单的 monthly schedule 配置测试,确认结构正确后再扩展。 ```bash # 最小可工作的 monthly schedule PUT _watcher/watch/ { "trigger": { "schedule": { "monthly": { "times": [ { "day": 1, "time": "00:00" } ] } } }, "input": {...}, "actions": {...} } ``` 3. **检查模板生成逻辑**:如果使用程序生成配置,确保序列化过程正确保留对象结构。 ### 后续注意事项与推荐建议 - 在编写 monthly schedule 配置时,严格参照官方文档中的示例。 - 对动态生成的配置进行结构验证,确保 `times` 是合法的对象数组。 - 在测试环境验证 schedule 配置,特别是在使用模板或程序生成配置时。 ### 借助 INFINI 产品提升排障效率 - **[INFINI Console](https://docs.infinilabs.com/console/main/)** 提供可视化的 Watch 编辑和验证功能,可以在保存前检查 schedule 配置的合法性,自动检测结构错误。 - **[INFINI Gateway](https://docs.infinilabs.com/gateway/main/)** 可以记录 Watcher API 的完整请求内容,帮助捕获 schedule 配置的详细错误上下文,并通过流量回放验证修复方案。 - 通过 INFINI Console 的 Watch 测试功能,可以在不执行完整 Watch 的情况下验证 schedule 配置的合法性。 ## 5. 小结 `could not parse month times. expected an object; but found [token]` 是一个结构类型错误,表示 monthly schedule 的 `times` 字段不是期望的对象结构。解决此问题的关键是:确认 `times` 是包含 `day` 和 `time` 字段的对象数组,修复 JSON 结构错误。 通过 INFINI Console 的配置验证功能和 INFINI Gateway 的请求捕获能力,可以更高效地定位和修复 monthly schedule 的结构问题。 ## 相关错误 - [could not parse week times expected an object but found - 如何解决此 Elasticsearch 异常](/knowledge-base/elasticsearch_error/could-not-parse-week-times-expected-an-object-but-found-how-to-solve-this-elasticsearch-exception/) - [could not parse year times expected an object but found - 如何解决此 Elasticsearch 异常](/knowledge-base/elasticsearch_error/could-not-parse-year-times-expected-an-object-but-found-how-to-solve-this-elasticsearch-exception/) - [could not parse schedule invalid weekly times - 如何解决此 Elasticsearch 异常](/knowledge-base/elasticsearch_error/could-not-parse-schedule-invalid-weekly-times-how-to-solve-this-elasticsearch-exception/) - [could not parse schedule invalid year times - 如何解决此 Elasticsearch 异常](/knowledge-base/elasticsearch_error/could-not-parse-schedule-invalid-year-times-how-to-solve-this-elasticsearch-exception/) - [could not parse schedule how to solve this elasticsearch exception - 如何解决此 Elasticsearch 异常](/knowledge-base/elasticsearch_error/could-not-parse-schedule-how-to-solve-this-elasticsearch-exception/) ## 参考文档 - [Elasticsearch Watcher Schedule Trigger 官方文档](https://www.elastic.co/guide/en/elasticsearch/reference/current/trigger-schedule.html) - [Monthly Schedule 配置参考](https://www.elastic.co/guide/en/elasticsearch/reference/current/trigger-schedule.html#schedule-monthly) - [INFINI Console 文档](https://docs.infinilabs.com/console/main/) - [INFINI Gateway 文档](https://docs.infinilabs.com/gateway/main/) ## 附:日志上下文 下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题: ```java public static MonthTimes parse(XContentParser parser, XContentParser.Token token) throws IOException, ElasticsearchParseException { if (token != XContentParser.Token.START_OBJECT) { throw new ElasticsearchParseException("could not parse month times. expected an object; but found [{}]", token); } ```