panjf2000/ants · error

invalid size for multiple pool

Error message

invalid size for multiple pool

What it means

ErrInvalidMultiPoolSize is returned by NewMultiPool, NewMultiPoolWithFunc and NewMultiPoolWithFuncGeneric when the requested number of sub-pools is invalid (e.g. negative). A MultiPool must contain at least one sub-pool, so construction is rejected up front.

Source

Thrown at ants.go:88

	ErrPoolClosed = errors.New("this pool has been closed")

	// ErrPoolOverload will be returned when the pool is full and no workers available.
	ErrPoolOverload = errors.New("too many goroutines blocked on submit or Nonblocking is set")

	// ErrInvalidPreAllocSize will be returned when trying to set up a negative capacity under PreAlloc mode.
	ErrInvalidPreAllocSize = errors.New("can not set up a negative capacity under PreAlloc mode")

	// ErrTimeout will be returned after the operations timed out.
	ErrTimeout = errors.New("operation timed out")

	// ErrInvalidPoolIndex will be returned when trying to retrieve a pool with an invalid index.
	ErrInvalidPoolIndex = errors.New("invalid pool index")

	// ErrInvalidLoadBalancingStrategy will be returned when trying to create a MultiPool with an invalid load-balancing strategy.
	ErrInvalidLoadBalancingStrategy = errors.New("invalid load-balancing strategy")

	// ErrInvalidMultiPoolSize  will be returned when trying to create a MultiPool with an invalid size.
	ErrInvalidMultiPoolSize = errors.New("invalid size for multiple pool")

	// workerChanCap determines whether the channel of a worker should be a buffered channel
	// to get the best performance. Inspired by fasthttp at
	// https://github.com/valyala/fasthttp/blob/master/workerpool.go#L139
	workerChanCap = func() int {
		// Use blocking channel if GOMAXPROCS=1.
		// This switches context from sender to receiver immediately,
		// which results in higher performance (under go1.5 at least).
		if runtime.GOMAXPROCS(0) == 1 {
			return 0
		}

		// Use non-blocking workerChan if GOMAXPROCS>1,
		// since otherwise the sender might be dragged down if the receiver is CPU-bound.
		return 1
	}()

	defaultLogger = Logger(log.New(os.Stderr, "[ants]: ", log.LstdFlags|log.Lmsgprefix|log.Lmicroseconds))

View on GitHub (pinned to 107e376781)

Solutions

  1. Pass a positive pool count (>= 1) to the NewMultiPool* constructors.
  2. Normalize config-derived counts: if size <= 0, fall back to runtime.NumCPU() or a fixed default.
  3. If one pool suffices, use NewPool/NewPoolWithFunc instead of MultiPool.

Example fix

// before
size := cfg.PoolCount // may be -1
mp, err := ants.NewMultiPool(size, 10, ants.RoundRobin)
// after
if cfg.PoolCount <= 0 {
    cfg.PoolCount = runtime.NumCPU()
}
mp, err := ants.NewMultiPool(cfg.PoolCount, 10, ants.RoundRobin)
Defensive patterns

Strategy: validation

Validate before calling

if poolCount <= 0 {
    poolCount = runtime.NumCPU()
}

Prevention

When it happens

Trigger: ants.NewMultiPool(-1, 10, ants.RoundRobin) or equivalent WithFunc/Generic constructors with a negative or zero pool count (size <= 0).

Common situations: Pool count derived from config or NumCPU-based heuristics that compute <= 0; placeholder -1 meaning 'auto' that the constructor does not accept.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of panjf2000/ants@107e376781 (2026-09-06). Data as JSON: /api/errors/bea8cfcf900b966e. Report an issue: GitHub.