{"record":{"id":"b4cd632ed0470872","repo":"micro/go-micro","slug":"invalid-connection-from-pool-b4cd63","errorCode":null,"errorMessage":"invalid connection from pool","messagePattern":"invalid connection from pool","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"transport/nats/nats.go","lineNumber":414,"sourceCode":"\n\tvar c *nats.Conn\n\tvar pooledConn *pooledConnection\n\tvar err error\n\n\t// Use connection pool if available\n\tn.mu.RLock()\n\thasPool := n.pool != nil\n\tn.mu.RUnlock()\n\n\tif hasPool {\n\t\tpooledConn, err = n.pool.Get()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tc = pooledConn.Conn()\n\t\tif c == nil {\n\t\t\t_ = n.pool.Put(pooledConn)\n\t\t\treturn nil, errors.New(\"invalid connection from pool\")\n\t\t}\n\t} else {\n\t\t// Create a new connection (original behavior)\n\t\topts := n.nopts\n\t\topts.Servers = n.addrs\n\t\topts.Secure = n.opts.Secure\n\t\topts.TLSConfig = n.opts.TLSConfig\n\t\topts.Timeout = dopts.Timeout\n\n\t\t// secure might not be set\n\t\tif n.opts.TLSConfig != nil {\n\t\t\topts.Secure = true\n\t\t}\n\n\t\tc, err = opts.Connect()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}","sourceCodeStart":396,"sourceCodeEnd":432,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/transport/nats/nats.go#L396-L432","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Enable/verify pool health pruning so closed conns are evicted instead of handed out","Reduce pool max-idle/keepalive so stale connections expire before reuse","Retry the Dial once — subsequent pool gets may return a valid connection","Upgrade/patch pool.Get to validate Conn() before returning, re-putting dead entries"],"exampleFix":"// caller-side before\nconn, err := t.Dial(\"nats\", dialOpts)\nif err != nil { return err }\n// after\nvar conn transport.Client\nfor i := 0; i < 2; i++ {\n\tconn, err = t.Dial(\"nats\", dialOpts)\n\tif err == nil { break }\n}","handlingStrategy":"retry","validationCode":"conn, err := t.Dial(\"nats\", opts...)\nif err != nil {\n\tif strings.Contains(err.Error(), \"invalid connection from pool\") {\n\t\tconn, err = t.Dial(\"nats\", opts...) // fresh attempt\n\t}\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"invalid connection from pool\") {\n\t// retry dial; if persistent, recreate the transport\n\treturn t.Dial(\"nats\", opts...)\n}","preventionTips":["Keep pool idle/keepalive settings below NATS server eviction limits","Validate/reap dead connections in the pool before reuse","Retry Dial on this specific error once before surfacing it","Watch NATS server logs for dropped idle connections"],"tags":["nats","transport","connection-pool","stale-connection"],"backgroundTag":"invalid-pooled-connection","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}