panjf2000/ants · error

invalid expiry for pool

Error message

invalid expiry for pool

What it means

ErrInvalidPoolExpiry is returned when a negative duration is configured as the pool's expiry (purge) interval. ants periodically purges idle workers; a negative ExpiryDuration is meaningless, so newPool (ants.go:216) rejects it at construction. Zero is allowed and falls back to DefaultCleanIntervalTime.

Source

Thrown at ants.go:67

	// DefaultCleanIntervalTime is the interval time to clean up goroutines.
	DefaultCleanIntervalTime = time.Second
)

const (
	// OPENED represents that the pool is opened.
	OPENED = iota

	// CLOSED represents that the pool is closed.
	CLOSED
)

var (
	// ErrLackPoolFunc will be returned when invokers don't provide function for pool.
	ErrLackPoolFunc = errors.New("must provide function for pool")

	// ErrInvalidPoolExpiry will be returned when setting a negative number as the periodic duration to purge goroutines.
	ErrInvalidPoolExpiry = errors.New("invalid expiry for pool")

	// ErrPoolClosed will be returned when submitting task to a closed pool.
	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")

View on GitHub (pinned to 107e376781)

Solutions

  1. Pass a positive duration to WithExpiryDuration (or omit it to use DefaultCleanIntervalTime).
  2. Validate/normalize config-sourced durations: if <= 0, use time.Duration(0) or a sane default before constructing the pool.
  3. Alternatively set WithDisablePurge(true) if you never want purging, which bypasses the expiry check.

Example fix

// before
pool, err := ants.NewPool(1000, ants.WithExpiryDuration(cfg.PurgeInterval))
// after
expiry := cfg.PurgeInterval
if expiry < 0 {
    expiry = 0 // ants falls back to DefaultCleanIntervalTime
}
pool, err := ants.NewPool(1000, ants.WithExpiryDuration(expiry))
Defensive patterns

Strategy: validation

Validate before calling

if expiry < 0 {
    return fmt.Errorf("expiry duration must be >= 0, got %s", expiry)
}
pool, err := ants.NewPool(size, ants.WithExpiryDuration(expiry))

Try / catch

if errors.Is(err, ants.ErrInvalidPoolExpiry) {
    // fix configuration and rebuild the pool
}

Prevention

When it happens

Trigger: ants.NewPool(-1, ants.WithExpiryDuration(-1)); any NewPool/NewPoolWithFunc/NewPoolWithFuncGeneric/NewMultiPool* call with WithExpiryDuration of a negative duration (checked inside newPool only when purge is enabled, i.e. DisablePurge is false).

Common situations: Computing the expiry from config/environment where a negative value slips through; accidentally swapping arguments so a size like -1 lands in the duration; copy-pasting test configs into production.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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