{"record":{"id":"71e164d6870d395c","repo":"t8y2/dbx","slug":"zookeeper-event-stream-closed-before-a-session-was","errorCode":null,"errorMessage":"ZooKeeper event stream closed before a session was established","messagePattern":"ZooKeeper event stream closed before a session was established","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/argo-go/discovery.go","lineNumber":201,"sourceCode":"\t}\n\tif len(cleaned) == 0 {\n\t\treturn \"/\"\n\t}\n\treturn \"/\" + strings.Join(cleaned, \"/\")\n}\n\nfunc waitForZooKeeperSession(ctx context.Context, events <-chan zk.Event, timeout time.Duration) error {\n\ttimer := time.NewTimer(timeout)\n\tdefer timer.Stop()\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn ctx.Err()\n\t\tcase <-timer.C:\n\t\t\treturn errors.New(\"ZooKeeper connection timed out before a session was established\")\n\t\tcase event, ok := <-events:\n\t\t\tif !ok {\n\t\t\t\treturn errors.New(\"ZooKeeper event stream closed before a session was established\")\n\t\t\t}\n\t\t\tif event.Err != nil {\n\t\t\t\treturn fmt.Errorf(\"ZooKeeper connection event: %w\", event.Err)\n\t\t\t}\n\t\t\tswitch event.State {\n\t\t\tcase zk.StateHasSession:\n\t\t\t\treturn nil\n\t\t\tcase zk.StateAuthFailed:\n\t\t\t\treturn errors.New(\"ZooKeeper authentication failed\")\n\t\t\tcase zk.StateExpired:\n\t\t\t\treturn errors.New(\"ZooKeeper session expired during connection\")\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc parseHiveServerRegistration(child string, data []byte) (endpoint, error) {\n\tcandidates := []string{strings.TrimSpace(string(data)), strings.TrimSpace(child)}","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/argo-go/discovery.go#L183-L219","documentation":"While waiting for a ZooKeeper session, the events channel is closed before a session event is delivered. A closed event stream means the underlying ZooKeeper client stopped (connection closed or client terminated) without ever establishing a session, so the wait aborts with this error instead of blocking forever.","triggerScenarios":"Endpoints() -> waitForZooKeeperSession receives ok=false from the events channel, e.g. the connection was closed by another goroutine or the client shut down before a session was established.","commonSituations":"Calling Close() on the ZooKeeper connection concurrently with discovery; the ZooKeeper client process crashing or being torn down by a shutdown hook; premature context cleanup closing the connection.","solutions":["Ensure nothing closes the ZooKeeper connection or client while Endpoints() is running","Re-create the ZooKeeper connection and retry discovery after an unexpected client shutdown","Check application shutdown ordering so discovery completes before teardown"],"exampleFix":"// before\ngo conn.Close() // closes while Endpoints is waiting\n// after\nendpoints, err := discovery.Endpoints(ctx) // then conn.Close() when done","handlingStrategy":"try-catch","validationCode":"// ensure connection stays open for the duration\nif conn == nil || conn.Closed() { return errors.New(\"zookeeper connection already closed\") }","typeGuard":null,"tryCatchPattern":"endpoints, err := discovery.Endpoints(ctx)\nif err != nil {\n\tif strings.Contains(err.Error(), \"event stream closed\") {\n\t\t// reconnect and retry; do not close conn concurrently\n\t}\n}","preventionTips":["Never call conn.Close() concurrently with Endpoints(); sequence discovery before shutdown","Use single-owner lifecycle management for the ZooKeeper connection","Add shutdown ordering: finish discovery, then close the client"],"tags":["zookeeper","connection","lifecycle"],"backgroundTag":"connection-closed-prematurely","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"}