astrid-runtime/astrid · error

stability quantiles must lie strictly between zero and 10,00

Error message

stability quantiles must lie strictly between zero and 10,000

What it means

`sampled_boundaries` validates each configured quantile, which must be expressed in basis points strictly between 0 and 10,000 (exclusive). Quantile 0 or >= 10000 would map to boundary index 0 or past the interior, so it is rejected as a configuration error.

Source

Thrown at crates/astrid-storage-chunker-evidence/src/stability.rs:149

        cases,
    })
}

fn sampled_boundaries(
    original: &[Chunk],
    quantiles_basis_points: &[u16],
) -> Result<Vec<(u16, usize)>> {
    let interior = original
        .get(..original.len().saturating_sub(1))
        .ok_or_else(|| anyhow::anyhow!("stability fixture has no interior boundary"))?;
    if interior.is_empty() {
        bail!("stability fixture has no interior boundary");
    }
    let mut sampled = Vec::with_capacity(quantiles_basis_points.len());
    let mut previous_index = None;
    for quantile in quantiles_basis_points {
        if *quantile == 0 || *quantile >= 10_000 {
            bail!("stability quantiles must lie strictly between zero and 10,000");
        }
        let index = usize::try_from(
            u64::try_from(interior.len())?
                .checked_mul(u64::from(*quantile))
                .and_then(|value| value.checked_div(10_000))
                .ok_or_else(|| anyhow::anyhow!("stability quantile overflow"))?,
        )?
        .min(
            interior
                .len()
                .checked_sub(1)
                .expect("the empty interior returned above"),
        );
        if previous_index == Some(index) {
            bail!("stability quantiles select duplicate boundary neighborhoods");
        }
        previous_index = Some(index);
        sampled.push((*quantile, interior[index].end));

View on GitHub (pinned to affd8760f4)

Solutions

  1. Convert values to basis points: 50% becomes 5000; keep every quantile in 1..=9999.
  2. Audit the quantile configuration source for percent-vs-basis-point confusion.
  3. Clamp/validate the quantile list before calling measure_fixture.
  4. Use named constants (e.g. QUANTILE_25PCT: u16 = 2500) to avoid magic-number mistakes.

Example fix

// before
let quantiles: &[u16] = &[0, 5000, 10_000];
// after
let quantiles: &[u16] = &[2500, 5000, 7500];
Defensive patterns

Strategy: validation

Validate before calling

fn valid_quantiles(quantiles: &[u16]) -> bool {
    quantiles.iter().all(|&q| (1..10_000).contains(&q))
}

Type guard

fn is_valid_basis_point_quantile(q: u16) -> bool {
    (1..10_000).contains(&q)
}

Try / catch

let quantiles: Vec<u16> = configured
    .iter()
    .copied()
    .filter(|&q| (1..10_000).contains(&q))
    .collect();
if quantiles.is_empty() { bail!("no valid quantiles configured"); }
measure_fixture(&fixture, &quantiles)?;

Prevention

When it happens

Trigger: Calling `measure_fixture` with a quantiles_basis_points list containing 0, 10_000, or a larger value — e.g. configuring a quantile as 1.0 instead of 10_000 basis points, or passing percentages (100) confused with basis points.

Common situations: Config mistakes where percent values (e.g. 50 for 50%) are used where basis points (5000) are required; off-by-one boundary values like 10000 intending 'the end'.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/3398a0fb7aacc745. Report an issue: GitHub.