vitessio/vitess · error

sample has zero variance

Error message

sample has zero variance

What it means

ErrZeroVariance is a sentinel error meaning all input samples have zero variance — every observation is identical — so the t-statistic denominator would be zero and the test is undefined. It is returned by TwoSampleTTest, TwoSampleWelchTTest, OneSampleTTest (when sample variance is 0) and PairedTTest (when the standard deviation of the differences is 0).

Source

Thrown at go/mathstats/ttest.go:80

	case LocationLess:
		p = dist.CDF(t)
	case LocationGreater:
		p = 1 - dist.CDF(t)
	}
	return &TTestResult{N1: n1, N2: n2, T: t, DoF: dof, AltHypothesis: alt, P: p}
}

// A TTestSample is a sample that can be used for a one or two sample
// t-test.
type TTestSample interface {
	Weight() float64
	Mean() float64
	Variance() float64
}

var (
	ErrSampleSize        = errors.New("sample is too small")
	ErrZeroVariance      = errors.New("sample has zero variance")
	ErrMismatchedSamples = errors.New("samples have different lengths")
)

// TwoSampleTTest performs a two-sample (unpaired) Student's t-test on
// samples x1 and x2. This is a test of the null hypothesis that x1
// and x2 are drawn from populations with equal means. It assumes x1
// and x2 are independent samples, that the distributions have equal
// variance, and that the populations are normally distributed.
func TwoSampleTTest(x1, x2 TTestSample, alt LocationHypothesis) (*TTestResult, error) {
	n1, n2 := x1.Weight(), x2.Weight()
	if n1 == 0 || n2 == 0 {
		return nil, ErrSampleSize
	}
	v1, v2 := x1.Variance(), x2.Variance()
	if v1 == 0 && v2 == 0 {
		return nil, ErrZeroVariance
	}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check Variance() (or StdDev of differences) before the call and short-circuit when it is 0
  2. Return a special 'no difference detected' result instead of running the test when variance is zero
  3. errors.Is(err, mathstats.ErrZeroVariance) to detect the constant-data case

Example fix

// before
res, err := mathstats.PairedTTest(before, after, 0, mathstats.LocationDiffers)
// after
res, err := mathstats.PairedTTest(before, after, 0, mathstats.LocationDiffers)
if errors.Is(err, mathstats.ErrZeroVariance) {
    return "no change between before and after", nil
}
Defensive patterns

Strategy: validation

Validate before calling

if x.Variance() == 0 { return errors.New("sample is constant; t-test undefined") }

Type guard

func hasVariance(s mathstats.TTestSample) bool { return s.Variance() > 0 }

Try / catch

res, err := mathstats.PairedTTest(a, b, 0, alt)
if errors.Is(err, mathstats.ErrZeroVariance) { return "no change", nil }

Prevention

When it happens

Trigger: TwoSampleTTest or TwoSampleWelchTTest with v1==0 && v2==0; OneSampleTTest with Variance()==0; PairedTTest when StdDev of x1[i]-x2[i] is 0 (identical pairs, e.g. x1 == x2).

Common situations: Comparing a dataset against itself; all rows returning the same metric value (e.g. a constant column, feature flag always off); paired test on before/after data where nothing changed.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/7cf3b176588cb98d. Report an issue: GitHub.