astrid-runtime/astrid · error

a corpus produced no chunks

Error message

a corpus produced no chunks

What it means

distribution computes chunk-size statistics and requires at least one (length, weight) pair; an empty distribution means the corpus produced no chunks at all, so percentiles and averages are undefined and the library bails.

Solutions

  1. Point the tool at a corpus containing at least one non-empty file.
  2. Ensure chunking actually ran and records were added before requesting the distribution.
  3. Handle the empty-corpus case in the caller and report a meaningful message instead of requesting stats.
Defensive patterns

Strategy: validation

Validate before calling

if total_chunks() == 0 { return Ok(None); } // skip distribution for empty corpus

Try / catch

match optional_distribution(&metrics) {
    Err(e) if e.to_string().contains("no chunks") => eprintln!("corpus produced no chunks"),
    other => other,
}

Prevention

When it happens

Trigger: optional_distribution invoked on a corpus where no chunks were ever recorded — empty inputs only, or all add_record calls skipped/failed before the summary was built.

Common situations: Running the evidence tool against an empty directory; a filter that excluded every input; a chunker that emitted nothing for all inputs.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — 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/5b0f8a383f91ea59. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-storage-chunker-evidence/src/metrics.rs:212

}

/// Returns the ratio in basis points, rounded down.
///
/// Retained and saved ratios are deliberately calculated independently with
/// this same rule. Deriving one as the complement of the other would round one
/// side up whenever the exact ratio is fractional.
fn basis_points(part: u64, total: u64) -> Result<u64> {
    if total == 0 {
        return Ok(0);
    }
    part.checked_mul(BASIS_POINTS)
        .and_then(|value| value.checked_div(total))
        .ok_or_else(|| anyhow::anyhow!("dedup ratio overflow"))
}

fn distribution(sorted: &[(u64, u64)]) -> Result<ChunkSizeDistributionBytes> {
    if sorted.is_empty() {
        bail!("a corpus produced no chunks");
    }
    let count = weighted_count(sorted)?;
    let sum = sorted.iter().try_fold(0_u64, |sum, (length, weight)| {
        let weighted = length
            .checked_mul(*weight)
            .ok_or_else(|| anyhow::anyhow!("weighted chunk length overflow"))?;
        checked_add(sum, weighted, "chunk-length sum")
    })?;
    let mean = sum
        .checked_div(count)
        .ok_or_else(|| anyhow::anyhow!("chunk distribution is empty"))?;
    Ok(ChunkSizeDistributionBytes {
        mean,
        minimum: sorted[0].0,
        p50: percentile(sorted, 50)?,
        p95: percentile(sorted, 95)?,
        p99: percentile(sorted, 99)?,
        maximum: sorted

View on GitHub (pinned to affd8760f4)