{"record":{"id":"96bb71fd77e63d0d","repo":"t8y2/dbx","slug":"root-znode-is-not-readable","errorCode":null,"errorMessage":"Root znode is not readable","messagePattern":"Root znode is not readable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/zookeeper/connection.go","lineNumber":252,"sourceCode":"\t}\n\n\tprefix := joinPrefix(target.Chroot, config.Namespace)\n\tretryBase := defaultBaseSleepTime\n\tif config.BaseSleepTimeMS != nil {\n\t\tretryBase = time.Duration(*config.BaseSleepTimeMS) * time.Millisecond\n\t}\n\tmaxRetries := defaultMaxRetries\n\tif config.MaxRetries != nil {\n\t\tmaxRetries = *config.MaxRetries\n\t}\n\tsession := &clientSession{connection: connection, prefix: prefix, retryBase: retryBase, maxRetries: maxRetries}\n\texists, _, err := session.Exists(\"/\")\n\tif err != nil || !exists {\n\t\tconnection.Close()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, errors.New(\"Root znode is not readable\")\n\t}\n\treturn session, nil\n}\n\nfunc newZooKeeperDialer(connectionTimeout time.Duration, credentials *saslDigestCredentials) zk.Dialer {\n\treturn func(network, address string, libraryTimeout time.Duration) (net.Conn, error) {\n\t\ttimeout := libraryTimeout\n\t\tif timeout <= 0 || connectionTimeout < timeout {\n\t\t\ttimeout = connectionTimeout\n\t\t}\n\t\tconnection, err := net.DialTimeout(network, address, timeout)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif credentials == nil {\n\t\t\treturn connection, nil\n\t\t}\n\t\treturn newSASLHandshakeConn(connection, timeout, *credentials), nil","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/zookeeper/connection.go#L234-L270","documentation":"After a session is established, openClient performs a sanity check with session.Exists(\"/\"). If that call fails, or reports the root znode does not exist / is not visible, the session is torn down and 'Root znode is not readable' is returned (any lower-level Exists error is returned verbatim instead).","triggerScenarios":"session.Exists(\"/\") returns exists==false with a nil error — the server accepted the session but the root znode is not readable by this client, e.g. due to ACLs. Raised in agents/drivers/zookeeper/connection.go:252.","commonSituations":"ZooKeeper configured with restrictive ACLs on / (e.g. world restricted or digest-only) so the client cannot stat the root; connecting through a chroot whose root is inaccessible; an authenticated-but-unauthorized user; server-side data directory issues making / disappear (rare).","solutions":["Verify the client's credentials have READ permission on the root znode (getAcl / from zkCli.sh) and fix ACLs (setAcl world:anyone:r or grant the digest user read).","Check the chroot portion of the connect string points to an existing, accessible znode.","Confirm with zkCli.sh that `ls /` works with the same credentials.","If the server intentionally restricts /, adjust the driver config to authenticate with a user that can read the root."],"exampleFix":"// server-side, zkCli.sh\n// before: getAcl / -> digest-only, client denied\n// after\nsetAcl / world:anyone:r","handlingStrategy":"try-catch","validationCode":"// Verify root readability with the same credentials out-of-band:\n// echo 'ls /' | zkCli.sh -server host:2181  -> must list \"/\" without ACL errors","typeGuard":null,"tryCatchPattern":"session, err := openClient(cfg)\nif err != nil {\n    if strings.Contains(err.Error(), \"Root znode is not readable\") {\n        return fmt.Errorf(\"zookeeper ACLs deny reading / for these credentials; grant READ on root or fix chroot: %w\", err)\n    }\n    return err\n}","preventionTips":["Audit root ACLs (getAcl /) whenever auth or chroot config changes","Keep world:anyone:r on / or ensure the digest user has READ on root","Test the chroot path exists and is accessible before deploying","Include an ACL smoke test in deployment health checks"],"tags":["zookeeper","acl","permissions","znode"],"backgroundTag":"acl-permission-denied","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}