risingwavelabs/risingwave · error
HyperLogLog: Count exceeds maximum bucket value.Your data st
Error message
HyperLogLog: Count exceeds maximum bucket value.Your data stream may have too many repeated values or too large acardinality for approx_count_distinct to handle (max: 2^64 - 1)
What it means
Each dense bucket in the updatable HyperLogLog stores its counter in a u64. When a non-retract update tries to increment a bucket already at u64::MAX, the addition would overflow, so the library refuses instead of silently wrapping. This implies an astronomically large number of repeated register hits (max cardinality 2^64 - 1), so it practically indicates corrupted or pathological state.
Source
Thrown at src/expr/impl/src/aggregate/approx_count_distinct/updatable.rs:132
sparse_counts: SparseCount::new(),
}
}
}
impl<const DENSE_BITS: usize> Bucket for UpdatableBucket<DENSE_BITS> {
fn update(&mut self, index: u8, retract: bool) -> Result<()> {
if index > 64 || index == 0 {
bail!("HyperLogLog: Invalid bucket index");
}
let count = self.get_bucket(index)?;
if !retract {
if index > DENSE_BITS as u8 {
self.sparse_counts.add(index);
} else if index >= 1 {
if count == u64::MAX {
bail!(
"HyperLogLog: Count exceeds maximum bucket value.\
Your data stream may have too many repeated values or too large a\
cardinality for approx_count_distinct to handle (max: 2^64 - 1)"
);
}
self.dense_counts[index as usize - 1] = count + 1;
}
} else {
// We don't have to worry about the user deleting nonexistent elements, so the counts
// can never go below 0.
if index > DENSE_BITS as u8 {
self.sparse_counts.subtract(index);
} else if index >= 1 {
self.dense_counts[index as usize - 1] = count - 1;
}
}
Ok(())View on GitHub (pinned to 6469eb736d)
Solutions
- Rebuild the materialized view / aggregation state to reset bucket counters.
- Check for state corruption from crash recovery or version migration and re-backfill the aggregation.
- File an issue if this reproduces with normal data volumes; real streams cannot legitimately hit this bound.
Defensive patterns
Strategy: validation
Validate before calling
// before incrementing, check the bucket
if !retract && bucket_count == u64::MAX {
return Err(anyhow!("bucket {} saturated", index));
} Type guard
fn can_increment(count: u64) -> bool { count < u64::MAX } Prevention
- Treat this error as a state-corruption signal; rebuild the MV.
- Monitor cardinality estimates; real workloads cannot saturate u64 buckets.
- Validate merged sketch registers before applying updates.
When it happens
Trigger: Calling `update(index, retract=false)` on a bucket whose current count equals u64::MAX; i.e. the same index incremented 2^64-1 times or a bucket pre-loaded with u64::MAX via merge/restore.
Common situations: Corrupted aggregation state in a materialized view; a merge of sketches with poisoned registers; extremely long-lived streaming jobs accumulating in one bucket (theoretical only).
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- event offset is too big, offset: {}
- Numeric out of range
- Numeric out of range: overflow
- HyperLogLog: Invalid bucket index
- HyperLogLog: Deletion in append-only bucket
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/0cc86871e411c143.
Report an issue: GitHub.