t8y2/dbx · error

Root znode is not readable

Error message

Root znode is not readable

What it means

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).

Source

Thrown at agents/drivers/zookeeper/connection.go:252

	}

	prefix := joinPrefix(target.Chroot, config.Namespace)
	retryBase := defaultBaseSleepTime
	if config.BaseSleepTimeMS != nil {
		retryBase = time.Duration(*config.BaseSleepTimeMS) * time.Millisecond
	}
	maxRetries := defaultMaxRetries
	if config.MaxRetries != nil {
		maxRetries = *config.MaxRetries
	}
	session := &clientSession{connection: connection, prefix: prefix, retryBase: retryBase, maxRetries: maxRetries}
	exists, _, err := session.Exists("/")
	if err != nil || !exists {
		connection.Close()
		if err != nil {
			return nil, err
		}
		return nil, errors.New("Root znode is not readable")
	}
	return session, nil
}

func newZooKeeperDialer(connectionTimeout time.Duration, credentials *saslDigestCredentials) zk.Dialer {
	return func(network, address string, libraryTimeout time.Duration) (net.Conn, error) {
		timeout := libraryTimeout
		if timeout <= 0 || connectionTimeout < timeout {
			timeout = connectionTimeout
		}
		connection, err := net.DialTimeout(network, address, timeout)
		if err != nil {
			return nil, err
		}
		if credentials == nil {
			return connection, nil
		}
		return newSASLHandshakeConn(connection, timeout, *credentials), nil

View on GitHub (pinned to c0390bff16)

Solutions

  1. 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).
  2. Check the chroot portion of the connect string points to an existing, accessible znode.
  3. Confirm with zkCli.sh that `ls /` works with the same credentials.
  4. If the server intentionally restricts /, adjust the driver config to authenticate with a user that can read the root.

Example fix

// server-side, zkCli.sh
// before: getAcl / -> digest-only, client denied
// after
setAcl / world:anyone:r
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify root readability with the same credentials out-of-band:
// echo 'ls /' | zkCli.sh -server host:2181  -> must list "/" without ACL errors

Try / catch

session, err := openClient(cfg)
if err != nil {
    if strings.Contains(err.Error(), "Root znode is not readable") {
        return fmt.Errorf("zookeeper ACLs deny reading / for these credentials; grant READ on root or fix chroot: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/96bb71fd77e63d0d. Report an issue: GitHub.