Skip to content

[BUG] ClassCastException for value-storing aggregates on nested PPL fields #4359

@ahkcs

Description

@ahkcs

What is the bug?
Value-storing aggregate functions (first(), last(), min(), max(), etc.) throw a ClassCastException when their argument is a deeply nested field accessed via dotted path wrapped in backticks (e.g., resource.attributes.telemetry.sdk.language). Calculation-only aggregates (count(), dc(), sum(), avg()) work as expected.


How can one reproduce the bug?
Steps to reproduce the behavior:

  1. Use an index matching logs-otel-v1* (or any index with similar nested object structure shown below).

  2. In PPL, run one of the following (value-storing aggregates with nested fields):

    source=logs-otel-v1* | stats first(`resource.attributes.telemetry.sdk.language`) by severityNumber
    source=logs-otel-v1* | stats last(`resource.attributes.telemetry.sdk.language`) by severityNumber
    source=logs-otel-v1* | stats min(`resource.attributes.telemetry.sdk.language`) by severityNumber
    source=logs-otel-v1* | stats max(`resource.attributes.telemetry.sdk.language`) by severityNumber
    
  3. Observe a 500 with ClassCastException in the response.

  4. Compare with working queries:

    -- calculation-only aggregates on the same nested path
    source=logs-otel-v1* | stats count(`resource.attributes.telemetry.sdk.language`) by severityNumber
    source=logs-otel-v1* | stats dc(`resource.attributes.telemetry.sdk.language`) by severityNumber
    -- simple fields work for all aggregates
    source=logs-otel-v1* | stats first(severityNumber)
    source=logs-otel-v1* | stats last(severityNumber)
    source=logs-otel-v1* | stats min(severityNumber)
    source=logs-otel-v1* | stats max(severityNumber)
    

What is the expected behavior?

  • first()/last() return the first/last non-null value of the nested field (e.g., "java").
  • min()/max() return the lexicographic min/max for keyword fields on the nested path.
  • All value-storing aggregates should accept nested dotted paths the same as simple fields—without throwing.

What is your host/environment?

  • Environment: [explore env]
  • Index Pattern: logs-otel-v1* (or similar)
  • Plugins: OpenSearch SQL (PPL)

Do you have any additional context?

Actual error response

{
  "error": {
    "reason": "There was internal problem at backend",
    "details": "class java.util.HashMap cannot be cast to class java.lang.String (java.util.HashMap and java.lang.String are in module java.base of loader 'bootstrap')",
    "type": "ClassCastException"
  },
  "status": 500
}

Function classification

  • Affected (value-storing): first(), last(), min(), max(), and any aggregate that returns the field value itself.
  • Unaffected (calculation-only): count(), dc(), sum(), avg().

Metadata

Metadata

Assignees

Labels

PPLPiped processing languagebugSomething isn't working

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions