JuliusBrussee/caveman · error

cachebench: provider %q engine-eligible population %d cannot

Error message

cachebench: provider %q engine-eligible population %d cannot meet minimum %d

What it means

validatePreparedReplayTarget found that after engine optimization, some provider has fewer cache-eligible requests (Decision Apply or ObserveOnly) than Target.MinEligibleRequest. This is the engine-filtered counterpart of error 881: raw population passed, but eligibility shrank it below the minimum.

Source

Thrown at cacheengine/cachebench/replay.go:551

	return prepared, nil
}

func validatePreparedReplayTarget(prepared []preparedReplay, target Target) error {
	if err := validateTarget(target); err != nil {
		return err
	}
	providers := map[string]bool{}
	eligible := map[string]int{}
	for _, item := range prepared {
		provider := strings.ToLower(strings.TrimSpace(item.record.Provider))
		providers[provider] = true
		if item.optimized.Decision == cacheengine.DecisionApply || item.optimized.Decision == cacheengine.DecisionObserveOnly {
			eligible[provider]++
		}
	}
	for provider := range providers {
		if eligible[provider] < target.MinEligibleRequest {
			return fmt.Errorf("cachebench: provider %q engine-eligible population %d cannot meet minimum %d", provider, eligible[provider], target.MinEligibleRequest)
		}
	}
	return nil
}

func (runner ReplayRunner) runSequential(ctx context.Context, prepared []preparedReplay, anchorTrace, anchorReal time.Time, now func() time.Time, sleep func(context.Context, time.Duration) error, emit func(ReplayResult) error) error {
	for _, item := range prepared {
		record := item.record
		traceAt, _ := time.Parse(time.RFC3339Nano, record.At)
		offset, _ := scaledReplayGap(traceAt.Sub(anchorTrace), runner.TimeScale)
		scheduled := anchorReal.Add(offset)
		if delay := scheduled.Sub(now().UTC()); delay > 0 {
			if err := sleep(ctx, delay); err != nil {
				return fmt.Errorf("cachebench: replay schedule interrupted: %w", err)
			}
		}
		started := now().UTC()
		evidence := replayEvidenceBase(record, item.optimized, runner.TimeScale, scheduled, started, runner.Limits.MaxScheduleDrift)

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Lower Target.MinEligibleRequest to fit the engine-eligible population.
  2. Add more records for the provider so enough survive engine eligibility filtering.
  3. Dry-run Optimize over the trace first and count eligible per provider, then set MinEligibleRequest within that budget.
  4. Relax the engine rules causing rejections (or its minimum-size threshold) to raise the eligible count.

Example fix

// before
target := cachebench.Target{MinEligibleRequest: 5} // only 2 survive engine filtering

// after
eligible := countEngineEligible(ctx, engine, records) // per provider
target := cachebench.Target{MinEligibleRequest: minInt(eligible["openai"], 5)}
Defensive patterns

Strategy: validation

Validate before calling

eligible := map[string]int{}
for _, r := range records {
    native, err := r.NativeRequest()
    if err != nil { continue }
    opt, err := engine.Optimize(ctx, native)
    if err != nil { continue }
    if opt.Decision == cacheengine.DecisionApply || opt.Decision == cacheengine.DecisionObserveOnly {
        eligible[strings.ToLower(strings.TrimSpace(r.Provider))]++
    }
}
for p, n := range eligible {
    if n < target.MinEligibleRequest { return fmt.Errorf("%s eligible %d < %d", p, n, target.MinEligibleRequest) }
}

Prevention

When it happens

Trigger: Calling Run with a target whose MinEligibleRequest is satisfied by raw counts but not after the engine marks some requests ineligible (below-threshold, refused). Example: 6 records for a provider, MinEligibleRequest 5, engine marks 3 ineligible.

Common situations: Traces where many requests fall below the engine's minimum cacheable size; strict engine rules rejecting part of the population; raising MinEligibleRequest without re-checking engine eligibility.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/9d97ea76988edf6d. Report an issue: GitHub.