Elasticsearch 9.5.6(2026-11-02)把 composite 聚合的 size 校验提前了:小于等于 0 直接 400,错误写明 [size] must be greater than 0。

9.5.5 同请求在有匹配文档时是 500,根因是 CompositeValuesCollectorQueue.top() 空指针。官方 PR #163307 说,这和 terms 聚合的拒法对齐;空索引时 9.5.5 以前还能默默回空 buckets,现在同样 400。下面用官方镜像 9.5.5 对照 9.5.6,再用 Spring Boot 4.1.2 的 RestClient 打同一条 _search。

9.5.5:size 为 0 且有文档时回 500 NPE

单节点关掉安全认证起镜像,建 keyword 字段 product,写入一条 sku-a。composite 的 size 写成 0:

===== curl 9.5.5 =====
VERSION=9.5.5
V955_SIZE0_HTTP=500
V955_SIZE0_BODY=null_pointer_exception: CompositeValuesCollectorQueue.top() is null; status=500
V955_SIZE1_HTTP=200
V955_SIZE1_BODY=buckets=[{"key":{"p":"sku-a"},"doc_count":1}]

size 改成 1 就正常分页。踩坑点很隐蔽:有人会把外层 hits 的 "size":0(只要聚合)抄到 composite 里,外层合法,内层却炸成 NPE。

9.5.6:解析阶段直接 400

同一条请求换到 9.5.6:

===== curl 9.5.6 =====
VERSION=9.5.6
V956_SIZE0_HTTP=400
V956_SIZE0_BODY=[size] must be greater than 0. Found [0] in [b]; status=400
V956_SIZE1_HTTP=200

请求还没进查询阶段就被拒,消息里带聚合名 b。size 为 1 仍是 200,行为与 9.5.5 一致。

Boot 4.1.2 RestClient:结论一致

业务侧常见是 Spring Boot 调 ES 做报表分页。演示用 Boot 4.1.2 的 RestClient 打 /orders/_search,不启 Web 端口。

===== boot RestClient 9.5.5 =====
BOOT=4.1.2
SIZE0_HTTP=500
SIZE1_HTTP=200

===== boot RestClient 9.5.6 =====
BOOT=4.1.2
SIZE0_HTTP=400
SIZE0_BODY=[size] must be greater than 0. Found [0] in [b]
SIZE1_HTTP=200

升到 9.5.6 后,原先偶发的 500 会变成稳定的 400。若客户端把 5xx 当可重试、4xx 当参数错误,监控和告警口径都要跟着改;自动化里写死 composite.size=0 的脚本会在升级后直接失败。

参考来源

— 感谢阅读 —
广告

一起交流

分享你的思考,让讨论更进一步。