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

适用版本: 6.8-8.9

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

invalid weekly day value. expected a string or a number value; but found [token] 是 Elasticsearch Watcher 模块在解析 weekly 类型定时触发器(schedule)时抛出的解析异常。该错误表示在 day 字段中传入的值既不是合法的字符串,也不是数字,而是一个不被接受的 JSON token 类型(如对象、数组、布尔值等)。

常见现象 #

  • 创建或更新 Watcher 时返回 400 Bad Request,错误信息中包含上述异常描述。
  • Kibana 或客户端调用 _watcher/watch/_execute_watcher/watch/{id}/_update 接口失败。
  • Elasticsearch 日志中出现 ElasticsearchParseException 堆栈,指向 DayOfWeek.resolve 解析逻辑。
  • Watcher 定时任务无法按预期触发,导致告警、数据同步等自动化任务失效。

典型报错示例 #

{
  "error": {
    "root_cause": [
      {
        "type": "parse_exception",
        "reason": "invalid weekly day value. expected a string or a number value; but found [START_OBJECT]"
      }
    ],
    "type": "parse_exception",
    "reason": "invalid weekly day value. expected a string or a number value; but found [START_OBJECT]"
  },
  "status": 400
}

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

该错误的根本原因是 Watcher 的 weekly schedule 在解析 day 字段时,对值的类型有严格限制。Elasticsearch 源码中只允许以下两种类型:

  • 字符串:如 "monday""tue""Wednesday" 等完整的星期名称或缩写。
  • 数字:如 1(星期一)到 7(星期日)的整数。

当解析器遇到其他 JSON token 类型时,会直接抛出 ElasticsearchParseException,而不会尝试类型转换。常见触发场景包括:

  • JSON 结构错误:将 day 的值写成了对象或数组,例如 {"day": "monday"}["monday", "friday"] 被错误地嵌套了一层。
  • 模板渲染异常:使用 Mustache 模板或外部脚本生成 Watcher 配置时,变量替换后产生了非预期的数据结构,如布尔值 true 或空对象 {}
  • 客户端序列化问题:某些 Elasticsearch 客户端在序列化时,将星期值错误地包装成了对象(如 JSON 库将枚举类型序列化为 {"value": "MONDAY"})。
  • 手动编辑失误:在手工编写 JSON 配置时,误加了花括号或方括号,导致值类型发生变化。

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

建议按以下顺序进行排查:

  1. 获取完整报错信息:从接口返回或 Elasticsearch 日志中确认 token 的具体类型(如 START_OBJECTSTART_ARRAYVALUE_BOOLEAN 等),这能直接指明问题方向。
  2. 检查 Watcher 配置的 trigger.schedule.weekly 部分:重点查看 day 字段的结构和值类型。
  3. 如果是通过模板动态生成配置,检查模板渲染前后的差异,确认变量替换是否产生了非预期的 JSON 结构。
  4. 使用 _watcher/watch/{id} GET 接口 查看当前已保存的 Watcher 定义,与期望的配置进行对比。
  5. 在本地或测试环境复现:用最小化的 JSON 配置逐步验证,排除其他配置项的干扰。

排查时需要注意的问题 #

  • day 字段可以是单个值,也可以是数组,但数组中的每个元素都必须是字符串或数字,不能是对象。
  • 星期字符串不区分大小写,但必须是 Elasticsearch 能识别的星期名称或缩写(如 montuewedthufrisatsun)。
  • 数字表示法中,1 代表星期一,7 代表星期日,与 java.time.DayOfWeek 的规范一致。
  • 如果该 Watcher 是通过 INFINI Console 或其他管理平台创建的,还需检查平台侧配置生成逻辑是否正确。

4. 如何解决这个错误 #

常用修复思路 #

修复前(错误示例) #

{
  "trigger": {
    "schedule": {
      "weekly": {
        "day": {"name": "monday"},
        "at": ["09:00", "18:00"]
      }
    }
  }
}
{
  "trigger": {
    "schedule": {
      "weekly": {
        "day": [{"value": "monday"}, {"value": "friday"}],
        "at": "10:00"
      }
    }
  }
}

修复后(正确示例) #

{
  "trigger": {
    "schedule": {
      "weekly": {
        "day": "monday",
        "at": ["09:00", "18:00"]
      }
    }
  }
}
{
  "trigger": {
    "schedule": {
      "weekly": {
        "day": ["monday", "friday"],
        "at": "10:00"
      }
    }
  }
}
{
  "trigger": {
    "schedule": {
      "weekly": {
        "day": [1, 5],
        "at": ["09:00", "17:00"]
      }
    }
  }
}

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

  • 在创建 Watcher 前,使用 JSON 校验工具验证配置的合法性,避免结构错误。
  • 如果 Watcher 配置由代码或模板生成,在生成后、提交前增加一层结构校验,确保 day 字段的类型符合预期。
  • 对于复杂的定时需求,优先考虑使用 cron 表达式替代 weekly schedule,灵活性和可读性都更好。
  • 定期审查 Watcher 配置,尤其是在进行模板或客户端库升级后,防止序列化行为变化引入新问题。

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

  • INFINI Console 提供可视化的 Watcher 管理界面,支持配置校验和实时预览,避免手写 JSON 产生结构错误。
  • INFINI Gateway 可以在请求到达 Elasticsearch 之前对 Watcher 相关 API 进行流量观测和异常请求拦截,帮助快速定位配置问题。
  • 建议将 Watcher 的执行日志和错误事件统一接入监控面板,在定时任务未按预期触发时第一时间收到告警。

5. 小结 #

invalid weekly day value 错误的核心在于 day 字段的值类型不符合 Elasticsearch 的解析要求。修复时只需确保 day 的值是字符串或数字(或由其组成的数组),避免嵌套对象或数组结构。对于通过模板或代码生成配置的场景,建议在提交前增加类型校验,从源头防止此类问题发生。

相关错误 #

附:日志上下文 #

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

if (token == XContentParser.Token.VALUE_STRING) {
    return DayOfWeek.resolve(parser.text());
}
if (token == XContentParser.Token.VALUE_NUMBER) {
    return DayOfWeek.resolve(parser.intValue());
}
throw new ElasticsearchParseException(
    "invalid weekly day value. expected a string or a number value; but found [" + token + "]"
);