{"record":{"id":"6320f072a16d6790","repo":"influxdata/influxdb","slug":"should-have-a-single-merged-statistic","errorCode":null,"errorMessage":"should have a single merged statistic","messagePattern":"should have a single merged statistic","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/iox_query/src/statistics/partition_statistics/mod.rs","lineNumber":258,"sourceCode":"}\n\nimpl PartitionStatistics for SortExec {\n    fn statistics_by_partition(&self) -> Result<PartitionedStatistics> {\n        if self.preserve_partitioning() {\n            preserve_partitioning_no_projection_apply_fetch(self, self.fetch(), 0)\n        } else {\n            merge_partitions_no_projection_apply_fetch(self, self.fetch(), 0)\n        }\n    }\n}\n\nimpl PartitionStatistics for RepartitionExec {\n    fn statistics_by_partition(&self) -> Result<PartitionedStatistics> {\n        // takes N input partitions, returning M output partitions.\n\n        // the statistics are \"merged\" into the same value (because any input can go to any output)\n        let mut merged = merge_partitions_no_projection(self)?;\n        let merged_single = merged.pop().expect(\"should have a single merged statistic\");\n        let merged_single = Arc::unwrap_or_clone(merged_single);\n\n        // then the merged stat is turned to inexact (since unknown division across output partitions)\n        let inexact_merged = Arc::new(Statistics {\n            num_rows: Precision::Absent,\n            total_byte_size: Precision::Absent,\n            column_statistics: make_column_statistics_inexact(merged_single.column_statistics),\n        });\n\n        // finally, all output partitions have the same merged stat\n        Ok(vec![inexact_merged; partition_count(self)])\n    }\n}\n\nimpl PartitionStatistics for AggregateExec {\n    fn statistics_by_partition(&self) -> Result<PartitionedStatistics> {\n        if self.aggr_expr().is_empty() {\n            let inner_stats_per_partition = statistics_by_partition(self.input.as_ref())?;","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/core/iox_query/src/statistics/partition_statistics/mod.rs#L240-L276","documentation":"Panics via `.expect(\"should have a single merged statistic\")` in RepartitionExec::statistics_by_partition. merge_partitions_no_projection is expected to return exactly one merged Statistics entry for repartitioned input; if it returns zero entries, the pop panics. This signals that input partition statistics were never produced.","triggerScenarios":"Calling statistics_by_partition on a RepartitionExec whose input yielded no partition statistics (empty merged vec), typically because the child executor's statistics are unavailable or the child plan has no partitions.","commonSituations":"Custom child executors returning empty statistics vectors; plans where repartition sits on top of a source that reports no row statistics; regressions after changing merge_partitions_no_projection.","solutions":["Verify the child executor of RepartitionExec reports statistics for its partitions","Make merge_partitions_no_projection return an error instead of an empty vec when inputs have no statistics","File a bug if this occurs with stock IOx/DataFusion plans"],"exampleFix":"// before\nlet merged_single = merged.pop().expect(\"should have a single merged statistic\");\n// after\nlet merged_single = merged.pop().ok_or_else(|| {\n    internal_datafusion_err!(\"repartition input produced no merged statistics\")\n})?;","handlingStrategy":"try-catch","validationCode":"if child.statistics()?.partition_statistics.is_empty() { /* skip repartition stats path */ }","typeGuard":null,"tryCatchPattern":"// wrap statistics_by_partition in catch_unwind for custom executors\nlet res = std::panic::catch_unwind(|| exec.statistics_by_partition());","preventionTips":["Ensure child executors always report statistics","Return Err instead of empty vecs from merge helpers","Test RepartitionExec over statistics-less sources"],"tags":["rust","panic","statistics","repartition"],"backgroundTag":"internal-invariant-violation","analyzedSha":"06200ef96ba82c5f6727e5038a83af8e722c6875","analyzedAt":"2026-09-19T12:55:30.003Z","contentChangedAt":"2026-09-19T12:55:30.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}