redis/go-redis · error

redis: no initConnFunc set for conn[%d]

Error message

redis: no initConnFunc set for conn[%d]

What it means

pool.Conn.ExecuteInitConn runs the deferred connection-initialization function (set by the pool during dialing — AUTH, SELECT, OnConnect hooks). If called when initConnFunc was never set, it returns 'redis: no initConnFunc set for conn[%d]'. This indicates an internal lifecycle bug or out-of-order use of the pool's low-level conn API rather than a normal user error.

Source

Thrown at internal/pool/conn.go:709

}

// SetOnCscReinit sets the client-side-caching pre-reinitialization hook,
// overwriting any previous one.
func (cn *Conn) SetOnCscReinit(fn func()) {
	cn.onCscReinit = fn
}

// SetInitConnFunc sets the connection initialization function to be called on reconnections.
func (cn *Conn) SetInitConnFunc(fn func(context.Context, *Conn) error) {
	cn.initConnFunc = fn
}

// ExecuteInitConn runs the stored connection initialization function if available.
func (cn *Conn) ExecuteInitConn(ctx context.Context) error {
	if cn.initConnFunc != nil {
		return cn.initConnFunc(ctx, cn)
	}
	return fmt.Errorf("redis: no initConnFunc set for conn[%d]", cn.GetID())
}

func (cn *Conn) SetNetConn(netConn net.Conn) {
	// Store the new connection atomically first (lock-free)
	cn.setNetConn(netConn)
	// Protect reader reset operations to avoid data races
	// Use write lock since we're modifying the reader state
	cn.readerMu.Lock()
	cn.rd.Reset(netConn)
	cn.readerMu.Unlock()

	cn.bw.Reset(netConn)

	// A new socket is a new server session with no HIMPORT fieldsets and
	// nothing left to discard.
	cn.ClearPreparedFieldsets(0)
}

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Only call ExecuteInitConn after pool.InitConn has run for that Conn
  2. Check for nil / lifecycle ordering in custom code that touches internal/pool.Conn directly
  3. If seen from stock go-redis usage, file an issue — it signals an internal race or bug
  4. Guard callers: check that the conn was dialed/initialized before executing init

Example fix

// before
cn := &pool.Conn{}
cn.ExecuteInitConn(ctx) // no initConnFunc set
// after
cn, err := pool.Dial(ctx)
if err == nil {
	cn.SetNetConn(netConn)
	cn.InitConn(ctx) // installs initConnFunc
	cn.ExecuteInitConn(ctx)
}
Defensive patterns

Strategy: validation

Try / catch

if err := cn.ExecuteInitConn(ctx); err != nil {
	if strings.Contains(err.Error(), "no initConnFunc set") {
		// conn was not initialized; re-run InitConn
		if ierr := cn.InitConn(ctx); ierr != nil {
			return ierr
		}
		return cn.ExecuteInitConn(ctx)
	}
	return err
}

Prevention

When it happens

Trigger: Calling ExecuteInitConn on a Conn created/reused before InitConn assigned initConnFunc; custom pool extensions or tests invoking ExecuteInitConn directly on a freshly created Conn; races where a conn is executed before its init function is installed.

Common situations: Custom forks or wrappers around internal/pool; reconnect logic that reuses Conn structs without re-running InitConn; unit tests of pool internals.

Related errors


AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01). Data as JSON: /api/errors/c254e49811dcb5db. Report an issue: GitHub.