affaan-m/ECC · error

scores must be finite and between 0 and 1

Error message

scores must be finite and between 0 and 1

What it means

`compare` validates each sample's `candidate_score` and `baseline_score`: both must be finite (not NaN or infinity) and within the inclusive range 0.0..=1.0. Non-finite or out-of-range values would corrupt mean, delta, and win-rate calculations. Any single bad sample causes the whole comparison to be rejected.

Solutions

  1. Normalize scores to [0,1] before constructing PairedSample (clamp and map the metric).
  2. Sanitize or drop non-finite scores (NaN/inf) before collecting samples.
  3. Check the upstream scoring function for NaN sources (empty outputs, division by zero).

Example fix

// before
let score = raw_value;
// after
let score = if raw_value.is_finite() { raw_value.clamp(0.0, 1.0) } else { 0.0 };
Defensive patterns

Strategy: validation

Validate before calling

anyhow::ensure!(
    samples.iter().all(|s| s.candidate_score.is_finite()
        && s.baseline_score.is_finite()
        && (0.0..=1.0).contains(&s.candidate_score)
        && (0.0..=1.0).contains(&s.baseline_score)),
    "sample scores must be finite and in [0,1]"
);

Try / catch

match evaluator.compare(&samples) {
    Ok(c) => c,
    Err(e) if e.to_string().contains("finite and between 0 and 1") => {
        eprintln!("Score out of range; check scoring/normalization step");
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `compare` with a sample whose score is NaN, infinite, negative, or greater than 1.0 — typically from an unnormalized metric or a failed/errored evaluation recorded as NaN.

Common situations: Metrics that are not normalized to [0,1] passed in directly, division-by-zero in score computation producing NaN, deserialized JSON containing null/defaulted scores, or a task that timed out and produced an infinite penalty score.

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


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/6a06a448f45097b2. Report an issue: GitHub.

Appendix: source

Thrown at ecc2/src/harness_eval.rs:539

        if samples.is_empty() {
            bail!("samples cannot be empty");
        }
        if samples
            .iter()
            .map(|sample| sample.seed)
            .collect::<BTreeSet<_>>()
            .len()
            != samples.len()
        {
            bail!("sample seeds must be unique");
        }
        if samples.iter().any(|s| {
            !s.candidate_score.is_finite()
                || !s.baseline_score.is_finite()
                || !(0.0..=1.0).contains(&s.candidate_score)
                || !(0.0..=1.0).contains(&s.baseline_score)
        }) {
            bail!("scores must be finite and between 0 and 1");
        }
        let count = samples.len();
        let candidate_mean = samples.iter().map(|s| s.candidate_score).sum::<f64>() / count as f64;
        let baseline_mean = samples.iter().map(|s| s.baseline_score).sum::<f64>() / count as f64;
        let mean_delta = candidate_mean - baseline_mean;
        let win_rate = samples
            .iter()
            .filter(|s| s.candidate_score > s.baseline_score)
            .count() as f64
            / count as f64;
        let mut failures = Vec::new();
        if count < self.min_samples {
            failures.push(format!(
                "minimum sample count is {}, got {count}",
                self.min_samples
            ));
        }
        if mean_delta < self.min_mean_delta {

View on GitHub (pinned to 8321021c54)