Describe the bug
Long story short, we use BeforeConnect to implement IAM Authentication with AWS / Aurora, and I traced back some panics to a missing logger in the context passed to BeforeConnect. I would expect the hook to receive a useful context (for logging, tracing, fetching credentials, ...), but while that happens for Pool.Acquire, the background goroutine refilling the pool to satisfy the minimum size calls it with a bare context.Background().
To Reproduce
Steps to reproduce the behavior:
package main
import (
"context"
"fmt"
"time"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
)
type key int
const myKey key = 0
func main() {
ctx := context.WithValue(context.Background(), myKey, "value")
poolConfig, _ := pgxpool.ParseConfig("postgres://user:password@127.0.0.1:1/mydb")
// Fail fast
poolConfig.ConnConfig.ConnectTimeout = 200 * time.Millisecond
// Prepare connections in the background
poolConfig.MinConns = 1
poolConfig.HealthCheckPeriod = 300 * time.Millisecond
var calls int
poolConfig.BeforeConnect = func(bcCtx context.Context, cc *pgx.ConnConfig) error {
calls++
if v := bcCtx.Value(myKey); v == nil {
fmt.Printf("call %d: BeforeConnect ctx MISSING value\n", calls)
} else {
fmt.Printf("call %d: BeforeConnect ctx has value=%q\n", calls, v)
}
return nil
}
pool, err := pgxpool.NewWithConfig(ctx, poolConfig)
if err != nil {
panic(err)
}
defer pool.Close()
// Let the background healthcheck fire a few times.
time.Sleep(2 * time.Second)
}
Expected behavior
call 1: ctx has value="value"
call 2: ctx has value="value"
call 3: ctx has value="value"
Actual behavior
call 1: ctx has value="value"
call 2: ctx MISSING value
call 3: ctx MISSING value
Call 1 comes from the initial idle creation goroutine in NewWithConfig. The subsequent ones come from backgroundHealthCheck + checkMinConns.
Impact
Anyone relying on context.Value propagation in BeforeConnect (e.g. injecting a request-scoped logger or AWS credential cache) sees inconsistent errors: the hook works on Acquire, it works on initial pool warm-up, but it randomly breaks on background refills. In our case it caused a nil-pointer panic while trying to log a message about the authentication.
Either re-use the context passed to NewWithConfig, expose a new Config.HealthCheckContext, or at the very least document the behavior to avoid unpleasant surprises. I can have a go at the first option if there's agreement.
Version
- Go: go1.26.2 darwin/arm64
- pgx: v5.9.1
- puddle: v2.2.2
Describe the bug
Long story short, we use
BeforeConnectto implement IAM Authentication with AWS / Aurora, and I traced back some panics to a missing logger in the context passed to BeforeConnect. I would expect the hook to receive a useful context (for logging, tracing, fetching credentials, ...), but while that happens forPool.Acquire, the background goroutine refilling the pool to satisfy the minimum size calls it with a barecontext.Background().To Reproduce
Steps to reproduce the behavior:
Expected behavior
Actual behavior
Call 1 comes from the initial idle creation goroutine in
NewWithConfig. The subsequent ones come frombackgroundHealthCheck+checkMinConns.Impact
Anyone relying on
context.Valuepropagation inBeforeConnect(e.g. injecting a request-scoped logger or AWS credential cache) sees inconsistent errors: the hook works onAcquire, it works on initial pool warm-up, but it randomly breaks on background refills. In our case it caused a nil-pointer panic while trying to log a message about the authentication.Either re-use the context passed to
NewWithConfig, expose a newConfig.HealthCheckContext, or at the very least document the behavior to avoid unpleasant surprises. I can have a go at the first option if there's agreement.Version