{"record":{"id":"1d827d927b794d3d","repo":"micro/go-micro","slug":"invalid-connection-from-pool","errorCode":null,"errorMessage":"invalid connection from pool","messagePattern":"invalid connection from pool","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"broker/nats/nats.go","lineNumber":240,"sourceCode":"\tn.RLock()\n\tdefer n.RUnlock()\n\n\tb, err := n.opts.Codec.Marshal(msg)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Use connection pool if enabled\n\tif n.pool != nil {\n\t\tpoolConn, err := n.pool.Get()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer func() { _ = n.pool.Put(poolConn) }()\n\n\t\tconn := poolConn.Conn()\n\t\tif conn == nil {\n\t\t\treturn errors.New(\"invalid connection from pool\")\n\t\t}\n\t\treturn conn.Publish(topic, b)\n\t}\n\n\t// Use single connection (original behavior)\n\tif n.conn == nil {\n\t\treturn errors.New(\"not connected\")\n\t}\n\n\treturn n.conn.Publish(topic, b)\n}\n\nfunc (n *natsBroker) Subscribe(topic string, handler broker.Handler, opts ...broker.SubscribeOption) (broker.Subscriber, error) {\n\tn.RLock()\n\thasConnection := n.conn != nil || n.pool != nil\n\tn.RUnlock()\n\n\tif !hasConnection {","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/broker/nats/nats.go#L222-L258","documentation":"When the NATS broker is configured with a connection pool, Publish checks out a pooled connection and verifies its underlying *nats.Conn is non-nil. If the pool hands back an entry whose connection is nil (a stale or improperly released pooled entry), Publish returns this error instead of panicking on a nil dereference. It indicates pool corruption or a connection that was closed and zeroed out without being evicted.","triggerScenarios":"Publishing with pooled mode enabled (n.pool != nil) when a pooled entry's Conn() returns nil — e.g. a pooled connection was closed elsewhere (NATS server restart, explicit Close) but its wrapper stayed in the pool at broker/nats/nats.go:240.","commonSituations":"NATS server restart or network drop that closes pooled connections while the broker keeps serving them from the pool; concurrent Close/Publish races; misconfigured pool warm-up creating placeholder entries with nil connections.","solutions":["Call broker.Connect() again to rebuild the pool with fresh live connections, then retry Publish.","Enable retry: reconnect the NATS client (nats.RetryOnFailedConnect, MaxReconnects) so closed pooled connections are re-established.","Check for concurrent broker.Disconnect()/Close() racing Publish; guard shutdown with proper synchronization.","Upgrade/patch the pool implementation so closed connections are evicted rather than reused."],"exampleFix":"// before\nif err := broker.Publish(ctx, \"events\", msg); err != nil {\n    return err\n}\n\n// after\nif err := broker.Publish(ctx, \"events\", msg); err != nil {\n    if strings.Contains(err.Error(), \"invalid connection from pool\") {\n        if cerr := broker.Connect(ctx); cerr != nil {\n            return cerr\n        }\n        return broker.Publish(ctx, \"events\", msg)\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":"// Before publishing, sanity-check NATS server reachability:\nnc, err := nats.Connect(natsURL, nats.Timeout(2*time.Second))\nif err != nil { return fmt.Errorf(\"nats unreachable: %w\", err) }\nif nc.Status() != nats.CONNECTED { return errors.New(\"nats not connected\") }\nnc.Close()","typeGuard":"func isInvalidPoolConn(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"invalid connection from pool\")\n}","tryCatchPattern":"err := br.Publish(ctx, topic, msg)\nif err != nil && strings.Contains(err.Error(), \"invalid connection from pool\") {\n    // rebuild pool / reconnect, then retry once\n    if cerr := br.Connect(ctx); cerr == nil {\n        err = br.Publish(ctx, topic, msg)\n    }\n}\nreturn err","preventionTips":["Configure the NATS client with MaxReconnects and RetryOnFailedConnect so pooled connections re-establish after server restarts.","Avoid racing broker.Disconnect()/Close() against in-flight Publish calls; synchronize shutdown.","Monitor NATS reconnect events and alert on pools serving closed connections.","Keep the broker/pool dependency updated so stale pooled entries are evicted on close."],"tags":["go","nats","connection-pool","publish"],"backgroundTag":"invalid-connection-from-pool","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}