affaan-m/ECC · error

minimum samples must be positive

Error message

minimum samples must be positive

What it means

`PromotionPolicy::validate` checks that `min_samples` is at least 1 before any statistical comparison. A policy requiring zero samples is meaningless — no result could ever fail the threshold — so it is rejected as a configuration mistake.

Solutions

  1. Set `min_samples` to a positive value (e.g. 30 for a reasonable paired-comparison baseline) before calling `compare`
  2. Validate the policy right after deserialization and fail with a clear config error
  3. Guard computed values with `min_samples.max(1)`

Example fix

// before
let policy = PromotionPolicy { min_samples: 0, .. };
let comparison = policy.compare(&samples)?;
// after
let policy = PromotionPolicy { min_samples: 30, .. };
let comparison = policy.compare(&samples)?;
Defensive patterns

Strategy: validation

Validate before calling

fn policy_is_valid(min_samples: usize) -> bool {
    min_samples > 0
}

Try / catch

match policy.compare(&samples) {
    Ok(comparison) => comparison,
    Err(e) if e.to_string().contains("minimum samples must be positive") => {
        eprintln!("PromotionPolicy misconfigured: {e}");
        // fall back to a sane default policy
        PromotionPolicy { min_samples: 30, ..policy }.compare(&samples)?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Constructing a `PromotionPolicy` with `min_samples: 0` (explicitly or via `Default`/partial builder) and then calling `compare` (or `validate` directly) on a sample slice.

Common situations: Deserializing a policy from JSON/TOML where min_samples defaulted to 0; a computed `min_samples` that underflowed; users confusing 'minimum extra samples' with total sample count.

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 affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/db7709b7ee9be4bd. Report an issue: GitHub.

Appendix: source

Thrown at ecc2/src/harness_eval.rs:508

    pub min_mean_delta: f64,
    pub min_win_rate: f64,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Comparison {
    pub passed: bool,
    pub sample_count: usize,
    pub candidate_mean: f64,
    pub baseline_mean: f64,
    pub mean_delta: f64,
    pub win_rate: f64,
    pub failures: Vec<String>,
}

impl PromotionPolicy {
    pub fn validate(self) -> Result<()> {
        if self.min_samples == 0 {
            bail!("minimum samples must be positive");
        }
        if !self.min_mean_delta.is_finite() {
            bail!("minimum mean delta must be finite");
        }
        if !self.min_win_rate.is_finite() || !(0.0..=1.0).contains(&self.min_win_rate) {
            bail!("minimum win rate must be between 0 and 1");
        }
        Ok(())
    }

    pub fn compare(self, samples: &[PairedSample]) -> Result<Comparison> {
        self.validate()?;
        if samples.is_empty() {
            bail!("samples cannot be empty");
        }
        if samples
            .iter()
            .map(|sample| sample.seed)

View on GitHub (pinned to 8321021c54)