kataras/iris · error

pool cannot be nil

Error message

pool cannot be nil

What it means

NewContextWrapper wraps a generic ContextPool[T] so custom context types can be used as Iris handlers. The library panics immediately at construction if the pool argument is nil, because the wrapper cannot function without a pool to acquire/release contexts. It is a fail-fast guard against a misconfigured generic wrapper.

Source

Thrown at context_wrapper.go:120

// ContextWrapper is a wrapper for handlers which expect a T instead of iris.Context.
//
// See the `NewContextWrapper` function for more.
type ContextWrapper[T any] struct {
	pool ContextPool[T]
}

// NewContextWrapper returns a new ContextWrapper.
// If pool is nil, a default pool is used.
// The default pool's AcquireFunc returns a zero value of T.
// The default pool's ReleaseFunc does nothing.
// The default pool is used when the pool is nil.
// Use the `iris.NewContextPool[T, *T]()` to pass a simple context pool.
// Then, use the `Handler` method to wrap custom handlers to iris ones.
//
// Example: https://github.com/kataras/iris/tree/main/_examples/routing/custom-context
func NewContextWrapper[T any](pool ContextPool[T]) *ContextWrapper[T] {
	if pool == nil {
		panic("pool cannot be nil")
	}

	return &ContextWrapper[T]{
		pool: pool,
	}
}

// Pool returns the pool, useful when manually Acquire and Release of custom context is required.
func (w *ContextWrapper[T]) Pool() ContextPool[T] {
	return w.pool
}

// Handler wraps the handler with the pool's Acquire and Release methods.
// It returns a new handler which expects a T instead of iris.Context.
// The T is the type of the pool.
// The T is acquired from the pool and released back to the pool after the handler's execution.
// The T is passed to the handler as an argument.
// The T is not shared between requests.

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Create the pool with iris.NewContextPool[T, *T]() and pass it to NewContextWrapper
  2. Ensure the variable holding the pool is initialized before route registration, not just declared
  3. If the pool comes from another function, check it for nil before calling NewContextWrapper

Example fix

// before
var pool iris.ContextPool[MyContext]
w := iris.NewContextWrapper(pool) // panics: pool cannot be nil
// after
pool := iris.NewContextPool[MyContext, *MyContext]()
w := iris.NewContextWrapper(pool)
Defensive patterns

Strategy: validation

Validate before calling

func safeNewContextWrapper[T any](pool iris.ContextPool[T]) *iris.ContextWrapper[T] {
    if pool == nil {
        pool = iris.NewContextPool[T, *T]()
    }
    return iris.NewContextWrapper(pool)
}

Type guard

func isNilPool[T any](pool iris.ContextPool[T]) bool {
    return pool == nil
}

Try / catch

// Go panics are not catchable idiomatically per-call; guard at startup:
func mustWrapper[T any](pool iris.ContextPool[T]) (w *iris.ContextWrapper[T]) {
    defer func() {
        if r := recover(); r != nil {
            log.Fatalf("NewContextWrapper failed: %v", r)
        }
    }()
    return iris.NewContextWrapper(pool)
}

Prevention

When it happens

Trigger: Calling iris.NewContextWrapper[T](nil), or passing a nil interface variable that was declared as ContextPool[T] but never assigned an implementation (e.g. the result of an uninitialized or failed iris.NewContextPool[T, *T]() call assigned to a nil-typed variable).

Common situations: Declaring `var pool iris.ContextPool[MyContext]` at package level and forgetting to initialize it before building routes; copying example code from the custom-context example and omitting the NewContextPool step; refactoring where pool construction was moved behind a flag or error path that silently skipped it.

Related errors


AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30). Data as JSON: /api/errors/74cc651bc3e48ed3. Report an issue: GitHub.