micro/go-micro · error

invalid connection from pool

Error message

invalid connection from pool

What it means

Dial consults the connection pool when pooling is enabled. If a pooled *pooledConnection's underlying nats.Conn is nil (e.g. the connection was closed or failed after being returned to the pool), Dial puts it back and returns this error. It signals a corrupted/invalid pooled connection rather than a dial failure.

Source

Thrown at transport/nats/nats.go:414

	var c *nats.Conn
	var pooledConn *pooledConnection
	var err error

	// Use connection pool if available
	n.mu.RLock()
	hasPool := n.pool != nil
	n.mu.RUnlock()

	if hasPool {
		pooledConn, err = n.pool.Get()
		if err != nil {
			return nil, err
		}
		c = pooledConn.Conn()
		if c == nil {
			_ = n.pool.Put(pooledConn)
			return nil, errors.New("invalid connection from pool")
		}
	} else {
		// Create a new connection (original behavior)
		opts := n.nopts
		opts.Servers = n.addrs
		opts.Secure = n.opts.Secure
		opts.TLSConfig = n.opts.TLSConfig
		opts.Timeout = dopts.Timeout

		// secure might not be set
		if n.opts.TLSConfig != nil {
			opts.Secure = true
		}

		c, err = opts.Connect()
		if err != nil {
			return nil, err
		}

View on GitHub (pinned to 24529f1404)

Solutions

  1. Enable/verify pool health pruning so closed conns are evicted instead of handed out
  2. Reduce pool max-idle/keepalive so stale connections expire before reuse
  3. Retry the Dial once — subsequent pool gets may return a valid connection
  4. Upgrade/patch pool.Get to validate Conn() before returning, re-putting dead entries

Example fix

// caller-side before
conn, err := t.Dial("nats", dialOpts)
if err != nil { return err }
// after
var conn transport.Client
for i := 0; i < 2; i++ {
	conn, err = t.Dial("nats", dialOpts)
	if err == nil { break }
}
Defensive patterns

Strategy: retry

Validate before calling

conn, err := t.Dial("nats", opts...)
if err != nil {
	if strings.Contains(err.Error(), "invalid connection from pool") {
		conn, err = t.Dial("nats", opts...) // fresh attempt
	}
}

Try / catch

if err != nil && strings.Contains(err.Error(), "invalid connection from pool") {
	// retry dial; if persistent, recreate the transport
	return t.Dial("nats", opts...)
}

Prevention

When it happens

Trigger: Calling transport.Dial on a NATS transport with connection pooling enabled (pool created via NewTransport pool options) when the pool hands back an entry whose Conn() is nil — typically after the server dropped the connection.

Common situations: Idle connections reaped by NATS server max-age/limits; pool not pruning closed connections; server restart leaving stale entries in the pool; long-running services where pooled conns expire.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/b4cd632ed0470872. Report an issue: GitHub.