panjf2000/ants · error

must provide function for pool

Error message

must provide function for pool

What it means

ErrLackPoolFunc is returned when a caller creates a worker pool without providing a task function. Pools created via NewPoolWithFunc and NewPoolWithFuncGeneric bind a single function at construction time, so a nil (or nil-typed) function argument makes the pool unusable and construction fails with this sentinel. It is a constructor-time validation error in ants.go:64.

Source

Thrown at ants.go:64

const (
	// DefaultAntsPoolSize is the default capacity for a default goroutine pool.
	DefaultAntsPoolSize = math.MaxInt32

	// 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")

View on GitHub (pinned to 107e376781)

Solutions

  1. Pass a non-nil function matching the required signature (e.g. func(i int)) to NewPoolWithFunc / NewPoolWithFuncGeneric.
  2. If the task function is variable, check for nil before constructing the pool and return a descriptive error.
  3. If you submit different closures per task, use ants.NewPool and pool.Submit(func) instead of the WithFunc variants.

Example fix

// before
var fn func(i int)
pool, err := ants.NewPoolWithFuncGeneric(10, fn)
// after
poolFunc := func(i int) { process(i) }
pool, err := ants.NewPoolWithFuncGeneric(10, poolFunc)
Defensive patterns

Strategy: validation

Validate before calling

if fn == nil {
    return fmt.Errorf("pool task function must not be nil")
}
pool, err := ants.NewPoolWithFuncGeneric(size, fn)

Type guard

func isNilFunc(fn any) bool {
    if fn == nil {
        return true
    }
    v := reflect.ValueOf(fn)
    return v.Kind() == reflect.Func && v.IsNil()
}

Prevention

When it happens

Trigger: Calling ants.NewPoolWithFunc(size, nil) or ants.NewPoolWithFuncGeneric(size, nil); also passing a declared-but-unassigned typed nil like `var fn func(i int); NewPoolWithFuncGeneric(1, fn)`.

Common situations: Declaring the task function variable but forgetting to assign it before pool construction; refactoring that removes a function argument; conditionally built functions that end up nil.

Related errors


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