astrid-runtime/astrid · error
percentile index is outside the distribution
Error message
percentile index is outside the distribution
What it means
percentile walks the sorted (length, weight) pairs accumulating weights until the target index is passed; if the cumulative weight never exceeds the index, the requested percentile lies outside the distribution, indicating internal inconsistency between the index computation and the distribution data.
Solutions
- Recompute the distribution and percentiles from the same immutable snapshot of data.
- Verify the percentile index is derived from the same weighted_count used to build the distribution.
- Report a bug if it occurs with the library's own percentile targets on unmodified data.
Defensive patterns
Strategy: try-catch
Validate before calling
fn index_in_range(index: u64, dist: &[(u64, u64)]) -> bool {
let total: u64 = dist.iter().map(|(_, w)| *w).sum();
index < total
} Try / catch
match dist.percentile(p) {
Err(e) if e.to_string().contains("outside the distribution") => recompute_distribution(),
other => other,
} Prevention
- Compute percentile indices from the same weighted_count as the distribution
- Never mutate distribution data after computing indices
- Freeze the measurement snapshot before computing statistics
When it happens
Trigger: Requesting a percentile whose index >= total weighted chunk count — caused by weighted_count/total drift, empty weight sums, or corrupted distribution pairs.
Common situations: Integer truncation bugs in index computation; distribution data modified after count was computed; metrics built from a corpus that changed mid-measurement.
Related errors
- a corpus produced no chunks
- a representation record must cover at least one logical…
- configure histogram buckets
- install Prometheus recorder
- recorder lock poisoned
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/36358693c09f680e.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-storage-chunker-evidence/src/metrics.rs:270
let total = sorted.iter().try_fold(0_u64, |count, (_, weight)| {
checked_add(count, *weight, "chunk count")
})?;
let last = total
.checked_sub(1)
.ok_or_else(|| anyhow::anyhow!("chunk distribution is empty"))?;
let index = last
.checked_mul(percentile)
.and_then(|value| value.checked_add(99))
.ok_or_else(|| anyhow::anyhow!("percentile index overflow"))?
/ 100;
let mut cumulative = 0_u64;
for (length, weight) in sorted {
cumulative = checked_add(cumulative, *weight, "chunk count")?;
if cumulative > index {
return Ok(*length);
}
}
bail!("percentile index is outside the distribution")
}
fn checked_add(left: u64, right: u64, label: &str) -> Result<u64> {
left.checked_add(right)
.ok_or_else(|| anyhow::anyhow!("{label} overflow"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dedup_ratios_are_exact_basis_points() {
assert_eq!(
deduplication(1_000, 471).unwrap(),
Deduplication {
retained_bytes: 471,
saved_bytes: 529,View on GitHub (pinned to affd8760f4)