{"record":{"id":"b959dc6bc0f3d379","repo":"t8y2/dbx","slug":"zookeeper-connection-is-nil","errorCode":null,"errorMessage":"ZooKeeper connection is nil","messagePattern":"ZooKeeper connection is nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/argo-go/zookeeper_protocol.go","lineNumber":143,"sourceCode":"\t\tevents := make(chan zk.Event, 1)\n\t\tevents <- zk.Event{State: zk.StateHasSession, Server: address}\n\t\tclose(events)\n\t\treturn client, events, nil\n\t}\n\treturn nil, nil, fmt.Errorf(\"connect and authenticate to ZooKeeper: %s\", strings.Join(failures, \"; \"))\n}\n\ntype protocolZooKeeperClient struct {\n\tconnection net.Conn\n\ttimeout    time.Duration\n\txid        int32\n\tmutex      sync.Mutex\n\tclosed     bool\n}\n\nfunc newProtocolZooKeeperClient(connection net.Conn, timeout time.Duration) (*protocolZooKeeperClient, error) {\n\tif connection == nil {\n\t\treturn nil, errors.New(\"ZooKeeper connection is nil\")\n\t}\n\tif timeout <= 0 {\n\t\ttimeout = defaultConnectTimeout\n\t}\n\tclient := &protocolZooKeeperClient{connection: connection, timeout: timeout}\n\trequest := &zooKeeperEncoder{}\n\trequest.int32(zooKeeperProtocolVersion)\n\trequest.int64(0)\n\trequest.int32(zooKeeperTimeoutMillis(timeout))\n\trequest.int64(0)\n\trequest.bytes(make([]byte, 16))\n\tif err := client.writeFrame(request.data()); err != nil {\n\t\treturn nil, fmt.Errorf(\"send ZooKeeper connect request: %w\", err)\n\t}\n\tresponse, err := client.readFrame()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read ZooKeeper connect response: %w\", err)\n\t}","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/argo-go/zookeeper_protocol.go#L125-L161","documentation":"newProtocolZooKeeperClient guards against constructing a protocol client around a nil net.Conn and returns this error immediately. A nil connection would panic later on first read/write, so the constructor converts it into a clear error. It can also be used defensively in tests/fakes that pass nil connections.","triggerScenarios":"Calling newProtocolZooKeeperClient(nil, timeout) directly or via connectKerberosZooKeeper when the underlying dialer returned (nil, nil) — e.g. a custom dial function or test fake that failed without reporting an error.","commonSituations":"Custom net.Dial wrappers that swallow dial errors and return a nil conn; mock/fake ZooKeeper connections in tests passing nil; refactored connection pools returning nil on exhausted connections.","solutions":["Fix the dialer/connection provider so it never returns a nil conn together with a nil error","Check the error from the dial step before constructing the protocol client","In tests, supply a real net.Pipe() or stub conn instead of nil","If you construct the client manually, validate the conn before calling"],"exampleFix":"// before\nconn, err := dialer.Dial(\"tcp\", addr) // may return nil, nil\nclient, err := newProtocolZooKeeperClient(conn, timeout)\n// after\nconn, err := dialer.Dial(\"tcp\", addr)\nif err != nil {\n    return fmt.Errorf(\"dial zookeeper: %w\", err)\n}\nif conn == nil {\n    return errors.New(\"dialer returned nil connection\")\n}\nclient, err := newProtocolZooKeeperClient(conn, timeout)","handlingStrategy":"type-guard","validationCode":"if conn == nil {\n    return errors.New(\"dialer returned nil connection\")\n}","typeGuard":"func validZooKeeperConn(c net.Conn) bool { return c != nil }","tryCatchPattern":"client, err := newProtocolZooKeeperClient(conn, timeout)\nif err != nil {\n    return fmt.Errorf(\"zookeeper client init: %w\", err)\n}","preventionTips":["Always check dial errors before constructing the client","Never return (nil, nil) from custom dialers","Use net.Pipe() stubs in tests instead of nil conns"],"tags":["zookeeper","nil-check","programming-error","go"],"backgroundTag":"nil-reference","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}