Repository navigation
[VL][Delta] Gluten Delta stats tracker should fall back when the stats plan can't be offloaded (ClassCastException on TIMESTAMP_NTZ) #12538
Description
Backend
VL (Velox)
Bug description
When Gluten collects Delta write statistics, GlutenDeltaJobStatsTracker builds a small local Velox aggregation plan and assumes the offload always succeeds, i.e. that the transformed plan is always a WholeStageTransformer. When the stats expression references a data type / expression that Velox does not yet support (for example TIMESTAMP_NTZ), offload validation correctly rejects the plan and it stays a vanilla Spark ProjectExec. The unconditional cast to WholeStageTransformer then throws a ClassCastException, failing the whole write.
Expected behavior: an unsupported type/expression in the Delta stats plan should induce a fallback to Spark's native Delta stats collection (the DeltaJobStatisticsTracker delegate path), not crash the write.
Actual behavior: the write task fails with:
java.lang.ClassCastException: class org.apache.spark.sql.execution.ProjectExec cannot be cast
to class org.apache.gluten.execution.WholeStageTransformer
at org.apache.spark.sql.delta.stats.GlutenDeltaJobStatsTracker$GlutenDeltaTaskStatsTracker.<init>(GlutenDeltaJobStatsTracker.scala:174)
at org.apache.spark.sql.delta.stats.GlutenDeltaJobStatsTracker.newTaskInstance(GlutenDeltaJobStatsTracker.scala:80)
at org.apache.spark.sql.execution.datasources.FileFormatDataWriter.$anonfun$statsTrackers$1(FileFormatDataWriter.scala:63)
at scala.collection.immutable.List.map(List.scala:236)
Root cause
In GlutenDeltaTaskStatsTracker the transform result is cast unconditionally:
val veloxTransformer = transformRule(projOp)
val wholeStageTransformer = ColumnarCollapseTransformStages(config)(veloxTransformer)
.asInstanceOf[WholeStageTransformer] // <-- throws when offload was rejected
.child
.asInstanceOf[TransformSupport]
transformRule runs the offload heuristic with a validator. If the stats expression contains something Velox can't handle (e.g. TIMESTAMP_NTZ in an aggregate/function), the validator rejects offload and transformRule returns the original vanilla ProjectExec. ColumnarCollapseTransformStages then leaves it as-is, and .asInstanceOf[WholeStageTransformer] fails.
This affects both source variants:
backends-velox/src-delta40/main/scala/org/apache/spark/sql/delta/stats/GlutenDeltaJobStatsTracker.scala(~line 174-177)backends-velox/src-delta33/main/scala/org/apache/spark/sql/delta/stats/GlutenDeltaJobStatsTracker.scala(~line 170-173)
How to reproduce
Run the Delta Spark UTs on the Gluten Velox bundle (as in #12388). Any test that collects Delta statistics on a TIMESTAMP_NTZ column reproduces it, e.g.:
data skipping on TIMESTAMP_NTZrecompute stats multiple columns and files
More generally: create/write a Delta table whose statistics columns include a type not yet offloadable by Velox and trigger stats collection.
Proposed fix
Per the discussion in #12388, rather than fixing TIMESTAMP_NTZ support itself (tracked separately in #11622), make the Gluten Delta stats path detect a rejected/failed offload and fall back to the native DeltaJobStatisticsTracker (or the existing fallback tracker) instead of assuming a WholeStageTransformer. Unsupported operations should induce a fallback for Delta plans generally.
Gluten version
main branch
Spark version
spark-4.0.x and later (reproduced on the Delta pipeline running Spark 4.1 / Delta v4.2.0; the same unchecked cast exists in the Delta 3.3 source variant).
References
- PR: [VL][Delta] Add Delta Spark UT pipeline gated against a known-failures baseline #12388 (Delta Spark UT pipeline; this failure is a baseline entry)
- Maintainer discussion: [VL][Delta] Add Delta Spark UT pipeline gated against a known-failures baseline #12388 (comment) and [VL][Delta] Add Delta Spark UT pipeline gated against a known-failures baseline #12388 (comment)
- Related type-support issue: [VL] Support TIMESTAMP_NTZ Type #11622 ([VL] Support TIMESTAMP_NTZ Type)
- CI run with repro: https://github.com/apache/gluten/actions/runs/29302276900/job/86989997438?pr=12388
This issue was written with the assistance of AI tooling (GitHub Copilot CLI).
Activity
[MINOR][DOC] Correct why the Delta tests fail
[CI] Don't run the Delta suite for documentation-only changes
felipepessoto commentedon Sep 2, 2026
facebookincubator/velox#17961 is merged.
Daily Velox, #12961 is also merged
We need something similar to #12654, but between DATE and TIMESTAMP_NTZ