Merge pull request #16725 from MichaHoffmann/mhoffmann/fix-topk-nan-arg-error-on-nonexisting-series

promql: fix topk error on NaN argument for non-existing series
This commit is contained in:
Björn Rabenstein 2025-07-08 19:42:20 +02:00 committed by GitHub
commit dbee82267a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 24 additions and 11 deletions

View File

@ -86,11 +86,6 @@ type engineMetrics struct {
querySamples prometheus.Counter
}
// convertibleToInt64 returns true if v does not over-/underflow an int64.
func convertibleToInt64(v float64) bool {
return v <= maxInt64 && v >= minInt64
}
type (
// ErrQueryTimeout is returned if a query timed out during processing.
ErrQueryTimeout string
@ -1433,6 +1428,15 @@ func (ev *evaluator) rangeEvalAgg(ctx context.Context, aggExpr *parser.Aggregate
if params.Max() < 1 {
return nil, annos
}
if params.HasAnyNaN() {
ev.errorf("Parameter value is NaN")
}
if fParam := params.Min(); fParam <= minInt64 {
ev.errorf("Scalar value %v underflows int64", fParam)
}
if fParam := params.Max(); fParam >= maxInt64 {
ev.errorf("Scalar value %v overflows int64", fParam)
}
seriess = make(map[uint64]Series, len(inputMatrix))
case parser.LIMIT_RATIO:
@ -1440,6 +1444,9 @@ func (ev *evaluator) rangeEvalAgg(ctx context.Context, aggExpr *parser.Aggregate
if params.Max() == 0 && params.Min() == 0 {
return nil, annos
}
if params.HasAnyNaN() {
ev.errorf("Ratio value is NaN")
}
if params.Max() > 1.0 {
annos.Add(annotations.NewInvalidRatioWarning(params.Max(), 1.0, aggExpr.Param.PositionRange()))
}
@ -3325,9 +3332,6 @@ seriesLoop:
var r float64
switch op {
case parser.TOPK, parser.BOTTOMK, parser.LIMITK:
if !convertibleToInt64(fParam) {
ev.errorf("Scalar value %v overflows int64", fParam)
}
k = int64(fParam)
if k > int64(len(inputMatrix)) {
k = int64(len(inputMatrix))
@ -3339,9 +3343,6 @@ seriesLoop:
return nil, annos
}
case parser.LIMIT_RATIO:
if math.IsNaN(fParam) {
ev.errorf("Ratio value %v is NaN", fParam)
}
switch {
case fParam == 0:
if enh.Ts != ev.endTimestamp {

View File

@ -388,6 +388,15 @@ eval_info instant at 50m bottomk by (instance) (1, {__name__=~"http_requests(_hi
{__name__="http_requests", group="production", instance="1", job="api-server"} 200
{__name__="http_requests", group="production", instance="2", job="api-server"} NaN
eval instant at 50m topk(NaN, non_existent)
expect fail msg: Parameter value is NaN
eval instant at 50m limitk(NaN, non_existent)
expect fail msg: Parameter value is NaN
eval instant at 50m limit_ratio(NaN, non_existent)
expect fail msg: Ratio value is NaN
clear
# Tests for count_values.

View File

@ -222,6 +222,9 @@ eval_warn instant at 50m histogram_quantile(NaN, testhistogram_bucket)
{start="positive"} NaN
{start="negative"} NaN
eval instant at 50m histogram_quantile(NaN, non_existent)
expect warn msg: PromQL warning: quantile value should be between 0 and 1, got NaN
# Quantile value in lowest bucket.
eval instant at 50m histogram_quantile(0, testhistogram)