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

适用版本: 6.8-7.17

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

invalid time minute value. expected string/number value; but found [token] 是 Elasticsearch Watcher 功能中的配置错误。当你在定义 Watcher 的定时调度(schedule)时,如果 minute 字段的值不是字符串或数字类型(比如传入了对象、数组、布尔值等),就会触发此错误。Watcher 的 cron 风格调度器要求 minute、hour、day 等时间字段必须是单个值或数组形式,且每个元素必须是字符串或数字。

常见现象 #

  • 创建或更新 Watcher 时返回 HTTP 400 Bad Request 状态码。
  • Watcher API 请求(PUT _watcher/<watch_id>)失败,响应中包含 ElasticsearchParseException
  • 在 Elasticsearch 服务端日志中会记录详细的异常信息和出错的配置路径。
  • 如果是通过 Kibana Watcher UI 或自动化脚本配置 Watcher,会收到错误提示。
  • 错误的 Watcher 配置不会被保存,因此不会影响现有的 Watcher 执行。

典型报错与异常栈 #

该异常的典型日志形态如下:

ElasticsearchParseException: invalid time minute value. expected string/number value; but found [{}]
    at org.elasticsearch.xpack.watcher.trigger.schedule.CronScheduleFactory.parseMinuteValue(CronScheduleFactory.java:...)
    at org.elasticsearch.xpack.watcher.trigger.schedule.CronScheduleFactory.parseSchedule(CronScheduleFactory.java:...)
    at org.elasticsearch.xpack.watcher.trigger.schedule.CronScheduleFactory.parse(CronScheduleFactory.java:...)
    at org.elasticsearch.xpack.watcher.trigger.schedule.ScheduleRegistry.parse(ScheduleRegistry.java:...)

通过 API 请求的响应通常如下:

{
  "error": {
    "root_cause": [
      {
        "type": "parse_exception",
        "reason": "invalid time minute value. expected string/number value; but found [{"value":15}]"
      }
    ],
    "type": "parse_exception",
    "reason": "invalid time minute value. expected string/number value; but found [{"value":15}]"
  },
  "status": 400
}

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

Watcher 的 cron 风格调度配置中,minutehourday_of_monthmonthday_of_week 等字段都有严格的类型要求。源码中的 parseMinuteValue 方法只接受两类输入:

  1. 数字类型:如 153045
  2. 字符串类型:如 "15""30""45"

如果传入其他类型,就会直接进入默认分支并抛出异常。常见原因包括:

  • 传入对象而非值:如 {"minute": {"value": 15}} 而不是 {"minute": 15}
  • 传入数组但元素类型错误:如 {"minute": [15, {"value": 30}]} 混合了正确和错误的元素类型
  • 模板渲染错误:使用 Mustache 模板或脚本生成配置时,可能错误地将对象赋值给了 minute 字段
  • JSON 结构错误:在构造 JSON 时,可能多了一层嵌套,导致实际值变成了对象
  • 类型自动转换问题:某些编程语言或 JSON 库在序列化时可能将数字转换为其他类型
  • 复制粘贴错误:从其他配置复制时,可能带入了错误的结构

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

排查步骤 #

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

第一步:获取完整的错误响应和请求体 #

# 重现错误并查看完整响应
curl -X PUT "localhost:9200/_watcher/watch/my_watch" -H 'Content-Type: application/json' -d @watch.json 2>&1 | jq .

# 查看 Elasticsearch 日志中的详细错误
tail -n 200 /var/log/elasticsearch/elasticsearch.log | grep -A 20 "invalid time minute value"

第二步:检查 Watcher 配置中的 minute 字段 #

# 使用 jq 检查 minute 字段的类型和结构
cat watch.json | jq '.trigger.schedule.minute'
# 应该输出数字或字符串,如 15 或 "15"

# 检查完整 schedule 配置
cat watch.json | jq '.trigger.schedule'

第三步:验证配置格式 #

// 错误示例:minute 的值是对象
{
  "trigger": {
    "schedule": {
      "minute": {"value": 15}  // 错误:应该是 15"15"
    }
  }
}

// 正确示例:minute 的值是数字
{
  "trigger": {
    "schedule": {
      "minute": 15
    }
  }
}

// 正确示例:minute 的值是字符串
{
  "trigger": {
    "schedule": {
      "minute": "15"
    }
  }
}

// 正确示例:minute 的值是数组
{
  "trigger": {
    "schedule": {
      "minute": [15, 30, 45]
    }
  }
}

第四步:在测试环境验证 #

# 在测试环境创建简单的 Watcher 进行验证
curl -X PUT "localhost:9200/_watcher/watch/test_watch" -H 'Content-Type: application/json' -d '
{
  "trigger": {
    "schedule": {
      "minute": "*/5",
      "hour": "*"
    }
  },
  "input": {
    "simple": {}
  },
  "condition": {
    "always": {}
  },
  "actions": {
    "log": {
      "logging": {
        "text": "Test watch triggered"
      }
    }
  }
}'

排查时需要注意的问题 #

  • 检查所有时间字段:不仅 minute,hour、day、month 等字段也有相同的类型要求。
  • 注意数组中的元素类型:如果 minute 是数组,数组中的每个元素都必须是数字或字符串。
  • 检查模板渲染结果:如果使用模板生成配置,检查渲染后的实际 JSON 结构。
  • 区分 cron 表达式和对象格式:Watcher 支持两种 schedule 格式:cron 表达式字符串和对象格式,不要混淆。

4. 如何解决这个错误 #

常用修复思路 #

方案一:修正 minute 值的类型 #

// 修复前:minute 值是对象
{
  "trigger": {
    "schedule": {
      "minute": {"value": 15, "type": "minute"}
    }
  }
}

// 修复后:minute 值是数字
{
  "trigger": {
    "schedule": {
      "minute": 15
    }
  }
}

方案二:使用字符串格式的 cron 表达式(更灵活) #

// 使用 cron 表达式字符串代替对象格式
{
  "trigger": {
    "schedule": {
      "cron": "0 */5 * * * ?"  // 每5分钟执行一次
    }
  }
}

方案三:修正模板或脚本生成逻辑 #

# Python 示例:确保生成正确的 minute 值
watch_config = {
    "trigger": {
        "schedule": {
            # 错误:minute: {"value": minute_value}
            # 正确:
            "minute": minute_value  # 确保这是数字或字符串类型
        }
    }
}

方案四:使用 Watcher API 验证配置 #

# 使用 _execute API 测试 Watcher 配置(不实际创建)
curl -X PUT "localhost:9200/_watcher/watch/_execute" -H 'Content-Type: application/json' -d '
{
  "watch": {
    "trigger": {
      "schedule": {
        "minute": 15
      }
    },
    ...
  }
}'

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

  • 建立配置验证流程:在将 Watcher 配置部署到生产环境之前,先在测试环境验证。
  • 使用 JSON Schema 验证:为 Watcher 配置定义 JSON Schema,在 CI/CD 流程中进行校验。
  • 统一时间配置规范:为团队制定 Watcher 调度配置的编码规范,避免类型错误。
  • 监控 Watcher 执行状态:通过 Watcher 历史记录查看执行状态,及时发现配置问题。
  • 考虑使用 cron 表达式:对于复杂的调度需求,使用 cron 表达式字符串可能比对象格式更直观。

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

  • INFINI Console 提供 Watcher 的可视化管理界面,可以直观地查看、编辑和测试 Watcher 配置。通过 Console 的配置验证功能,可以在保存前检查配置的正确性,避免因类型错误导致的异常。Console 还提供 Watcher 执行历史查看,帮助快速定位配置问题。

  • INFINI Gateway 可以拦截和检查发往 Elasticsearch 的 Watcher API 请求,自动检测并拒绝包含类型错误的配置。Gateway 还提供请求重写功能,可以在请求到达 Elasticsearch 之前自动修正常见的配置错误,保护后端集群的稳定性。

  • 对于依赖大量 Watcher 进行定时任务管理的团队,建议结合 INFINI Console 的可视化配置管理功能和 INFINI Gateway 的请求治理能力,建立从 Watcher 设计、验证、部署到监控的完整流程,大幅减少因配置错误导致的异常。

5. 小结 #

invalid time minute value. expected string/number value; but found 是一个典型的 Watcher 配置类型错误,根源在于 minute 字段的值类型不符合要求。虽然报错信息直接指向类型问题,但修复时需要仔细检查整个 schedule 配置的结构,确保每个时间字段的值都是数字或字符串类型。

在实际工作中,为避免此类问题,建议在开发阶段使用 INFINI Console 的可视化工具来构造和验证 Watcher 配置,在 CI/CD 流程中加入配置格式检查,并使用 INFINI Gateway 作为防护层来拦截错误的配置请求。通过工具化和流程化的方式,可以大幅减少此类类型错误的发生。

相关错误 #

参考文档 #

附:日志上下文 #

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

default:
    throw new ElasticsearchParseException("invalid time minute value. expected string/number value; but found [{}]", token);