vitessio/vitess · error
negative capacity
Error message
negative capacity
What it means
ConnPool.setCapacity panics when asked to shrink/expand the pool to a negative capacity. Capacity is an int64 atomic and a negative value has no meaning, so the internal setter fails fast instead of corrupting pool accounting (oldcap swap, drain logic).
Source
Thrown at go/pools/smartconnpool/pool.go:853
// If the capacity is smaller than the number of connections that there are
// currently open, we'll close enough connections before returning, even if
// that means waiting for clients to return connections to the pool.
// If the given context times out before we've managed to close enough connections
// an error will be returned.
func (pool *ConnPool[C]) SetCapacity(ctx context.Context, newcap int64) error {
pool.capacityMu.Lock()
defer pool.capacityMu.Unlock()
if pool.close.Load() == nil {
return ErrConnPoolClosed
}
return pool.setCapacity(ctx, newcap)
}
// setCapacity is the internal implementation for SetCapacity; it must be called
// with pool.capacityMu being held
func (pool *ConnPool[C]) setCapacity(ctx context.Context, newcap int64) error {
if newcap < 0 {
panic("negative capacity")
}
oldcap := pool.capacity.Swap(newcap)
// Skip the drain only when capacity is unchanged AND we're already at or
// below the target. Otherwise we may have been left with active > newcap
// by a prior call that timed out (e.g. SetCapacity(0) racing with held
// conns), and CloseWithContext relies on a follow-up call here to finish
// draining.
if oldcap == newcap && pool.active.Load() <= newcap {
return nil
}
// update the idle count to match the new capacity if necessary
// wait for connections to be returned to the pool if we're reducing the capacity.
defer pool.setIdleCount()
const delay = 10 * time.Millisecond
// close connections until we're under capacityView on GitHub (pinned to 01a25a7d17)
Solutions
- Validate the new capacity before calling SetCapacity: if newcap < 0, clamp to 0 or reject the change
- Fix the computation that produced the negative value (log/inspect oldcap and delta)
- Sanitize configuration at startup so negative pool sizes are rejected in PreRun/config validation
Example fix
// before
pool.SetCapacity(ctx, current-int64(released)) // may be negative
// after
newCap := current - int64(released)
if newCap < 0 {
newCap = 0
}
pool.SetCapacity(ctx, newCap) Defensive patterns
Strategy: validation
Validate before calling
if newCap < 0 {
return fmt.Errorf("invalid capacity %d", newCap)
}
pool.SetCapacity(ctx, newCap) Type guard
func validCapacity(n int64) bool { return n >= 0 } Prevention
- Clamp computed capacities to >= 0 before calling SetCapacity
- Validate pool size config at startup and reject negatives
- Never derive capacity from unvalidated arithmetic on external input
When it happens
Trigger: Calling pool.SetCapacity(ctx, n) (or resize paths) with a negative n, e.g. n computed as current - delta where delta exceeds current, or parsing a negative config value.
Common situations: Config with a negative capacity value; arithmetic like SetCapacity(cap-overflow) after accounting for connections about to be released; integer underflow in autoscaling code.
Related errors
- SetIdleTimeout called when timer not initialized
- panic: %v
- timestampBusy when borrowing a time
- err
- Value.ForEachValue on non-tuple
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/be51d33461bbab88.
Report an issue: GitHub.