8000 fix(api): reject the percentile aggregations on a non-numeric field by amartya1523 · Pull Request #2989 · xerj-org/xerj · GitHub
[go: up one dir, main page]

Skip to content

fix(api): reject the percentile aggregations on a non-numeric field - #2989

Open
amartya1523 wants to merge 2 commits into
xerj-org:mainfrom
amartya1523:fix/percentiles-field-type
Open

amartya1523 wants to merge 2 commits into
xerj-org:mainfrom
amartya1523:fix/percentiles-field-type

Conversation

@amartya1523
Copy link
Copy Markdown
Contributor

AI-assisted change, run and reviewed by @amartya1523.

What this changes, and why

percentiles on a keyword field answered 200 with every percentile null:

POST /test_1/_search {"size":0,"aggs":{"a":{"percentiles":{"field":"string_field","hdr":{}}}}}
-> 200 "aggregations":{"a":{"values":{"1.0":null,"5.0":null,"25.0":null,"50.0":null,...}}}

That reads as "this index has no values", not "this is the wrong field". ES registers the percentile aggregations for numeric values only: percentiles and percentile_ranks also take date and boolean, median_absolute_deviation is numeric only. So on a keyword or ip field, ValuesSourceRegistry#getAggregator fails every shard and the search is a 400:

Field [string_field] of type [keyword] is not supported for aggregation [percentiles]

Two catch-lenient.txt lines are this case:

  • aggregations/percentiles_hdr_metric.yml · Invalid params test
  • aggregations/percentiles_tdigest_metric.yml · Invalid params test

Each YAML case has several steps (bad number_of_significant_value_digits, negative compression, empty/null/non-numeric percents, and a keyword field). The new test replays every step against main: all the others already answer 400; only the keyword-field step, the last one in each case, failed.

Fix (es_compat.rs): find_unsupported_metric_agg_field already does this for avg, sum, min, max, stats and extended_stats (#2913). It now covers percentiles, percentile_ranks and median_absolute_deviation too, with the same rules:

  • only types ES never accepts for them (keyword, constant_keyword, wildcard, ip, geo_point, version)
  • only when the field has such a type in every target index, since ES answers a partial 200 otherwise
  • after the field-alias rewrite, so an alias is judged by the field it names
  • through the same search_shard_validation_error envelope

No new function: the change is the list of aggregation names and the doc comment.

Evidence

New test module percentile_family_field_type_tests (es_compat.rs), run against main first:

# main 83c9f0d12
test es_compat::percentile_family_field_type_tests::invalid_percentile_requests_are_a_400 ... FAILED
  {"field":"string_field","hdr":{}} -> {... "aggregations":{"a":{"values":{"1.0":null,"5.0":null, ...
test es_compat::percentile_family_field_type_tests::numeric_percentile_requests_still_answer ... ok

# this branch
test es_compat::percentile_family_field_type_tests::invalid_percentile_requests_are_a_400 ... ok
test es_compat::percentile_family_field_type_tests::numeric_percentile_requests_still_answer ... ok
  • First test: all twelve steps of the two YAML cases return 400. Then percentiles on keyword and ip, percentile_ranks on keyword, and median_absolute_deviation on keyword each assert ES's exact reason.

  • Second test:

    • percentiles on an integer (hdr) and on a date
    • percentile_ranks on a double
    • median_absolute_deviation on an integer
    • percentiles over /test_1,other, where other maps the field as a long

    All still answer 200.

Checks

  • cargo fmt -p xerj-api -- --check
  • cargo test --profile quick -p xerj-api --lib: 432 passed, 0 failed, including the existing metric_agg_field_type_tests
  • YAML: both existing Invalid params test cases now enforce it; their catch-lenient lines are deleted. The other percentile cases use numeric fields.
  • Docs: none describe the old behaviour.

Not run locally:

  • The ES-YAML suite, --release builds, clippy and the integration binaries. Disk on this machine is at 99%; CI runs all of these.

Provenance

  • Written by: AI-assisted, run and reviewed by @amartya1523
  • Verified: the test outputs above, on macOS 26 (aarch64), quick profile, based on main 83c9f0d12.
  • Assumed:
    • The per-aggregation value-source registrations follow ES's PercentilesAggregationBuilder, PercentileRanksAggregationBuilder and MedianAbsoluteDeviationAggregationBuilder.
    • boxplot (x-pack analytics) is numeric-only in ES too, but it has no YAML case here, so I left it out of this PR. I can add it if you want.

ES registers percentiles, percentile_ranks and median_absolute_deviation
for numeric values only (plus date and boolean for the percentiles), so
one on a keyword or ip field fails every shard with "Field [f] of type
[t] is not supported for aggregation [percentiles]" and the search is a
400. XERJ answered 200 with every percentile null, which reads as an
empty index rather than the wrong field.

The check that already does this for avg/sum/min/max/stats/
extended_stats now covers the three, with the same rules: only types ES
never accepts, and only when the field has that type in every target.

Retires the two percentiles_{hdr,tdigest}_metric.yml Invalid params
entries; every other step of both cases already answered 400.
Replays every step of both Invalid params cases; keyword and ip fields are a 400 with ES's reason for percentiles, percentile_ranks and median_absolute_deviation. Numeric, date and mixed-index targets still answer.
@cla-bot cla-bot Bot added the cla-signed label Nov 6, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0