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

适用版本: 6.8-7.15

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

invalid dynamic name expression [expr]. date math placeholder is open ended 表示 Elasticsearch 在解析动态索引名时,发现 date math 占位符开了头但没有正确结束。Elasticsearch 支持在索引名中使用 date math 表达式来实现基于时间的自动索引路由(如按天、月、年自动滚动索引),当占位符 < 开头后没有对应的 > 结尾时,就会触发此异常。

常见现象 #

  • 执行搜索、写入或索引管理操作时返回 400 Bad Request 错误。
  • 错误响应中包含 invalid dynamic name expressiondate math placeholder is open ended 信息。
  • 在 Elasticsearch 日志中可以看到 ElasticsearchParseException 相关堆栈。
  • 常见于使用日期数学表达式的索引模式,如 <logs-{now/d}><index-{now/M}> 等。

典型报错与异常栈 #

{
  "error": {
    "root_cause": [
      {
        "type": "parse_exception",
        "reason": "invalid dynamic name expression [<logs-{now/d]>. date math placeholder is open ended"
      }
    ],
    "type": "parse_exception",
    "reason": "invalid dynamic name expression [<logs-{now/d]>. date math placeholder is open ended"
  },
  "status": 400
}

底层 Java 异常栈通常类似:

ElasticsearchParseException: invalid dynamic name expression [<logs-{now/d]>. date math placeholder is open ended
    at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver$ExpressionResolver.resolve(IndexNameExpressionResolver.java:...)
    at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver.resolveExpression(IndexNameExpressionResolver.java:...)

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

该异常的根本原因是动态索引名表达式中的 date math 占位符没有正确闭合。常见原因包括:

  • 缺少结束尖括号 >:date math 表达式以 < 开头,必须以 > 结尾。如果忘记写 >,解析器会认为占位符未闭合。
  • 花括号不匹配:date math 表达式内部使用 {} 包裹动态部分,如果花括号不匹配,也会导致解析失败。
  • 模板渲染截断:当索引名通过模板引擎(如 Jinja2、Freemarker 等)或字符串拼接生成时,如果变量替换后导致后半段被截断,就会产生不完整的表达式。
  • 转义字符问题:在某些上下文中,> 可能被转义或解释为其他含义,导致实际传递给 Elasticsearch 的索引名缺少结束符。
  • 多层嵌套错误:在复杂表达式中,多层 date math 嵌套时容易遗漏某个结束符。
  • 手动拼接错误:开发者手动拼接索引名字符串时,遗漏了结尾的 > 字符。

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

建议按以下步骤进行排查:

  1. 提取完整索引名表达式:从错误信息中获取 dynamic name expression 后面的具体内容,确认是哪个索引名表达式有问题。

  2. 检查占位符闭合:确认表达式是否以 < 开头、以 > 结尾,并且 <> 数量匹配。

  3. 检查花括号匹配:date math 内部的动态部分应该用 {} 包裹,确认花括号成对出现。

  4. 追溯表达式来源:确认索引名是从哪里生成的——是硬编码在代码中、通过模板渲染、还是通过字符串拼接。

  5. 打印最终表达式:在发送请求前,打印最终生成的索引名字符串,确认其完整性。

排查命令示例 #

# 查看 Elasticsearch 日志中的 date math 解析错误
grep -r "date math placeholder is open ended" /var/log/elasticsearch/

# 测试正确的 date math 索引表达式
curl -X GET "localhost:9200/<logs-{now/d}>" -H "Content-Type: application/json"

# 测试带格式的 date math 表达式
curl -X GET "localhost:9200/<logs-{now/d{yyyy-MM-dd}}>" -H "Content-Type: application/json"

# 查看索引模板中是否使用了 date math
curl -X GET "localhost:9200/_index_template" -H "Content-Type: application/json"

# 检查应用程序生成的索引名(假设应用在本地运行)
# 在应用日志中搜索索引名生成相关的日志
grep -r "index.*name\|index.*pattern" /path/to/app/logs/

4. 如何解决这个错误 #

常用修复思路 #

  • 补齐结束符:确保 date math 表达式以 > 正确结尾。基本的 date math 索引名格式为 <name-{date_math_expression}>

  • 检查花括号匹配:确保 {} 内的 date math 表达式完整且正确闭合。

  • 避免手动拼接:不要手工拼接半截索引名表达式,使用专门的索引名构建工具或函数。

  • 模板渲染检查:如果索引名通过模板引擎生成,确认模板变量替换后不会产生不完整的表达式。

  • 在请求发出前验证:在发送请求前打印最终索引名,确保其格式正确。

修复示例 #

// 错误示例:缺少结束符 >
// 错误:<logs-{now/d}
curl -X GET "localhost:9200/<logs-{now/d}" -H "Content-Type: application/json"

// 错误:花括号不匹配
// 错误:<logs-{now/d>
curl -X GET "localhost:9200/<logs-{now/d>" -H "Content-Type: application/json"

// 正确示例:完整闭合
// 正确:<logs-{now/d}>
curl -X GET "localhost:9200/<logs-{now/d}>" -H "Content-Type: application/json"

// 正确示例:带自定义格式
// 正确:<logs-{now/d{yyyy-MM-dd}}>
curl -X GET "localhost:9200/<logs-{now/d{yyyy-MM-dd}}>" -H "Content-Type: application/json"

// 正确示例:按月滚动
// 正确:<logs-{now/M}>
curl -X GET "localhost:9200/<logs-{now/M}>" -H "Content-Type: application/json"
// Java 应用层构建索引名的示例
public class IndexNameBuilder {
    public static String buildDailyIndexName(String baseName, LocalDate date) {
        // 正确格式:<baseName-yyyy.MM.dd>
        String dateStr = date.format(DateTimeFormatter.ofPattern("yyyy.MM.dd"));
        return "<" + baseName + "-" + dateStr + ">";
    }

    public static String buildDateMathIndex(String baseName) {
        // 正确格式:<baseName-{now/d}>
        return "<" + baseName + "-{now/d}>";
    }
}

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

  • 在使用 date math 表达式时,始终遵循 <name-{date_math_expression}> 的格式,确保开头和结尾的尖括号都完整。
  • 对于通过模板或字符串拼接生成的索引名,建议在生成后做一次格式校验,检查 <>{} 是否匹配。
  • 在开发环境多测试不同的 date math 表达式,熟悉其语法规则,避免在生产环境写出错误格式。

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

  • INFINI Console 可以查看 Elasticsearch 集群的索引分布、索引创建趋势和请求日志,帮助快速定位哪些请求使用了错误的索引名表达式,以及这些请求的来源和频率。

  • INFINI Gateway 部署在 Elasticsearch 前面时,可以对所有请求进行观测和审计。当遇到索引名表达式错误时,Gateway 可以记录完整的请求上下文,包括请求头、请求体和索引名,帮助快速定位问题。Gateway 还支持请求改写功能,可以在请求到达 Elasticsearch 之前对索引名进行校验和修正。

  • 对于大量使用 date math 表达式的业务场景,INFINI Console 的索引管理功能可以直观展示索引的创建规律和命名模式,帮助发现索引名生成逻辑中的问题。

5. 小结 #

invalid dynamic name expression [expr]. date math placeholder is open ended 是一个典型的 date math 索引名解析异常,根因几乎总是占位符未正确闭合。处理该异常时,应先检查索引名表达式是否以 < 开头、以 > 结尾,并确认内部的花括号匹配。避免手动拼接索引名字符串,使用专门的工具函数生成索引名。结合 INFINI Console 的请求审计和 INFINI Gateway 的请求治理能力,可以从根源上减少此类异常的发生。

相关错误 #

参考文档 #

附:日志上下文 #

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

if (inPlaceHolder) {
    throw new ElasticsearchParseException("invalid dynamic name expression [{}]. date math placeholder is open ended",
        new String(text, from, length));
}