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
- No action required — this is expected self-protection; the throttler keeps the conservative limit.
- If rates legitimately recovered, keep reporting rates; bad values age out and limits can be raised via the throttler API.
- 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
- Treat this as informational — log at debug level, don't alert.
- Don't construct rate histories that oscillate around the bad rate in tests without expecting this.
- Rely on sustained rate reports rather than single spikes to raise limits.
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
- ignoring lower bad rate of %v because such a high degradatio
- BUG: limiter was unable to reserve an event. threadThrottler
- invalid NewMaxReplicationLagModuleConfig: %v
- target_replication_lag_sec must not be higher than max_repli
- invalid max replication lag config: %w
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/3dbe8cb6234720f8.
Report an issue: GitHub.