vitessio/vitess · info

ignoring higher good rate of %v because we assume that the k

Error message

ignoring higher good rate of %v because we assume that the known maximum capacity (currently at %v) can only degrade

What it means

The throttler's memory module refuses to record a 'good' rate higher than the lowest bad rate ever observed, on the assumption that maximum capacity can only degrade, not improve. The proposed good rate is ignored and this error is returned (logged by the throttler).

Source

Thrown at go/vt/throttler/memory.go:87

	m.badRateIncrease = badRateIncrease
}

// int64Slice is used to sort int64 slices.
type int64Slice []int64

func (a int64Slice) Len() int           { return len(a) }
func (a int64Slice) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a int64Slice) Less(i, j int) bool { return a[i] < a[j] }

func searchInt64s(a []int64, x int64) int {
	return sort.Search(len(a), func(i int) bool { return a[i] >= x })
}

func (m *memory) markGood(rate int64) error {
	rate = m.roundDown(rate)

	if lowestBad := m.lowestBad(); lowestBad != 0 && rate > lowestBad {
		return fmt.Errorf("ignoring higher good rate of %v because we assume that the known maximum capacity (currently at %v) can only degrade", rate, lowestBad)
	}

	// Skip rates which already exist.
	i := searchInt64s(m.good, rate)
	if i < len(m.good) && m.good[i] == rate {
		return nil
	}

	m.good = append(m.good, rate)
	sort.Sort(int64Slice(m.good))
	return nil
}

func (m *memory) markBad(rate int64, now time.Time) error {
	// Bad rates are rounded up instead of down to not be too extreme on the
	// reduction and account for some margin of error.
	rate = m.roundUp(rate)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. No action required — this is expected self-protection; the throttler keeps the conservative limit.
  2. If rates legitimately recovered, keep reporting rates; bad values age out and limits can be raised via the throttler API.
  3. Restart/recreate the throttler if the recorded bad rate is stale and no longer representative.
Defensive patterns

Strategy: try-catch

Validate before calling

if lowestBad := mem.LowestBadForTest(); lowestBad != 0 && rate > lowestBad {
    // expect rejection; skip reporting
}

Try / catch

if err := mem.markGood(rate); err != nil {
    log.Debug("good rate ignored by memory module", slog.Any("error", err))
}

Prevention

When it happens

Trigger: markCurrentRateAsBadOrGood calls memory.markGood(rate) when the current rate exceeds m.lowestBad(); typically right after a rate was marked bad and the observed rate bounces above it.

Common situations: Replica catch-up causes a sudden throughput spike above the previously recorded bad rate; benchmark-style bursts right after a throttler rate-limit event.

Related errors


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