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
- Only call ExecuteInitConn after pool.InitConn has run for that Conn
- Check for nil / lifecycle ordering in custom code that touches internal/pool.Conn directly
- If seen from stock go-redis usage, file an issue — it signals an internal race or bug
- 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
- Never call ExecuteInitConn directly on Conns you did not dial via the pool
- Run InitConn before ExecuteInitConn in custom pool code
- If it reproduces with stock go-redis, report it with a minimal repro and goroutine dump
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
- failed to create connection closed metric: %w
- failed to create connection pending requests metric: %w
- redis: failed to create connection pool: %w
- redis: failed to create connection pool: %w
- redis: failed to create pubsub pool: %w
AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01).
Data as JSON: /api/errors/c254e49811dcb5db.
Report an issue: GitHub.