适用版本: 6.8-8.9
1. 错误异常的基本描述 #
array elements in include/exclude clauses should be string values(include/exclude 子句中的数组元素应为字符串值)是 Elasticsearch 在解析查询 DSL 时抛出的 illegal_argument_exception 类型异常。该错误明确表示:在 include 或 exclude 数组中,出现了非字符串类型的元素。
此错误常见于以下两种场景:
- 聚合查询(Aggregations):在使用
terms聚合时,通过include或exclude参数指定需要包含或排除的字段值,但传入了数值、布尔值或对象等非字符串类型。 - Source 过滤:在使用
_source的includes/excludes参数时,数组中包含非字符串元素。
常见现象 #
- 请求返回 HTTP
400 Bad Request,错误类型为illegal_argument_exception。 - Elasticsearch 服务端日志中出现
ElasticsearchParseException: Array elements in include/exclude clauses should be string values。 - 应用侧表现为查询失败,相关聚合结果或搜索结果无法返回。
- 在 Kibana Dev Tools 或客户端代码中直接执行查询时立即报错。
典型报错与异常栈 #
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "array elements in include/exclude clauses should be string values"
}
],
"type": "illegal_argument_exception",
"reason": "array elements in include/exclude clauses should be string values"
},
"status": 400
}
服务端日志中的异常栈通常类似:
ElasticsearchParseException: Array elements in include/exclude clauses should be string values
at org.elasticsearch.search.aggregations.bucket.terms.IncludeExclude.merge(IncludeExclude.java:...)
at org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder.doRewrite(TermsAggregationBuilder.java:...)
at org.elasticsearch.search.aggregations.AggregationBuilder.rewrite(AggregationBuilder.java:...)
2. 为什么会发生这个错误 #
Elasticsearch 的 include / exclude 机制设计上只接受 字符串数组 作为参数值。其底层实现通过 XContentParser 解析请求体时,会逐个校验数组元素的类型,一旦发现非字符串 token(如数值、布尔值、START_OBJECT 等),立即抛出 ElasticsearchParseException。
常见原因 #
- 数值类型误用:在
include/exclude数组中直接写入数字,如[1, 2, 3],而 Elasticsearch 期望的是["1", "2", "3"]。 - 布尔类型误用:写入
true/false而非"true"/"false"。 - 对象类型误用:在数组中嵌套了对象或数组,而非纯字符串。
- 客户端 SDK 序列化问题:某些 SDK 在序列化时,将原本是字符串的数字字段值序列化为数值类型,导致请求体不符合要求。
- 动态生成查询时类型丢失:通过代码动态拼接查询 DSL 时,变量类型未显式转换为字符串。
3. 如何排查这个异常 #
建议按以下步骤定位问题:
- 获取完整报错信息:确认错误类型为
illegal_argument_exception,且reason字段包含array elements in include/exclude clauses should be string values。 - 检查查询 DSL:重点检查
aggregations下的terms聚合中的include/exclude字段,以及_source的includes/excludes字段。 - 使用最小复现 DSL:将查询简化为只保留触发异常的聚合或过滤部分,逐步定位具体是哪个数组元素类型不正确。
- 核对字段类型:确认目标字段的 mapping 类型,理解其值是字符串还是数值,从而判断
include/exclude中应使用何种格式的字符串。 - 检查客户端代码:如果是通过代码动态生成查询,检查变量类型是否正确转换为字符串。
排查注意事项 #
include/exclude同时支持 字符串数组 和 正则表达式字符串 两种形式,但不能混用,也不能在数组中包含非字符串元素。- 数值类型的字段值(如
keyword类型的数字字符串)在include/exclude中仍需用字符串形式表示。
4. 如何解决这个错误 #
场景一:聚合查询中的 include/exclude 数组包含数值 #
错误示例:
{
"aggs": {
"tags": {
"terms": {
"field": "category",
"include": [1, 2, 3]
}
}
}
}
修复后:
{
"aggs": {
"tags": {
"terms": {
"field": "category",
"include": ["1", "2", "3"]
}
}
}
}
场景二:include/exclude 中包含布尔值 #
错误示例:
{
"aggs": {
"status_filter": {
"terms": {
"field": "status",
"include": [true, false]
}
}
}
}
修复后:
{
"aggs": {
"status_filter": {
"terms": {
"field": "status",
"include": ["true", "false"]
}
}
}
}
场景三:_source 过滤中的 includes/excludes 数组类型错误 #
错误示例:
{
"_source": {
"includes": ["title", 123, true]
},
"query": {
"match_all": {}
}
}
修复后:
{
"_source": {
"includes": ["title", "123", "true"]
},
"query": {
"match_all": {}
}
}
场景四:使用正则表达式时的正确写法 #
include / exclude 也支持直接传入正则表达式字符串(非数组形式):
{
"aggs": {
"tags": {
"terms": {
"field": "category",
"include": "app.*",
"exclude": "test.*"
}
}
}
}
客户端代码示例(Python) #
# 错误写法
include_values = [1, 2, 3]
# 正确写法:显式转换为字符串
include_values = [str(v) for v in [1, 2, 3]] # ["1", "2", "3"]
query = {
"aggs": {
"tags": {
"terms": {
"field": "category",
"include": include_values
}
}
}
}
5. 预防建议与最佳实践 #
- 显式类型转换:在动态生成查询 DSL 时,始终将
include/exclude数组元素显式转换为字符串类型,避免依赖语言的隐式类型推断。 - 查询 DSL 校验:在将查询发送到 Elasticsearch 之前,使用 JSON Schema 或自定义校验逻辑检查
include/exclude数组元素类型。 - 统一封装查询构建方法:在项目中封装专门的聚合查询构建方法,确保
include/exclude参数始终以字符串数组形式传入。 - 使用正则表达式替代长数组:当需要包含或排除大量值时,优先考虑使用正则表达式形式,减少数组长度,同时避免类型错误。
- 在测试环境验证查询:涉及动态参数拼接的查询,应在测试环境使用真实数据进行验证,提前发现类型问题。
借助 INFINI 产品提升排障效率 #
- INFINI Console 适合查看集群健康度、索引状态、查询错误趋势,帮助快速判断异常是查询构造问题还是集群层面的问题。
- INFINI Gateway 适合部署在 Elasticsearch 前面做请求观测、DSL 审计和流量治理,可以在请求到达 Elasticsearch 之前拦截并记录不合法的查询 DSL,便于提前发现问题。
6. 小结 #
array elements in include/exclude clauses should be string values 是一个典型的查询 DSL 类型错误,根因在于 include / exclude 数组中包含非字符串类型的元素。修复方法非常直接:确保所有数组元素均为字符串类型。通过显式类型转换、统一查询构建方法和在网关层做请求审计,可以有效预防此类问题再次发生。
相关错误 #
- illegal-argument-exception:非法参数异常
- parse-exception:解析异常
- unknown-parameter:未知参数错误
- validation-exception:验证异常
附:源码上下文 #
以下为 Elasticsearch 源码中触发此异常的相关逻辑,便于深入理解错误触发路径:
if (parser.currentToken() != XContentParser.Token.START_ARRAY) {
throw new ElasticsearchParseException("Missing start of array in include/exclude clause");
}
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
if (parser.currentToken().isValue() == false) {
throw new ElasticsearchParseException("Array elements in include/exclude clauses should be string values");
}
set.add(new BytesRef(parser.text()));
}
return set;





