t8y2/dbx · error
Root znode cannot be modified
Error message
Root znode cannot be modified
What it means
put normalizes the request key into a znode path and refuses to write the root: if path == "/" it returns 'Root znode cannot be modified'. The ZooKeeper root znode is structural and this driver forbids creating/overwriting it, so keys that normalize to the root are rejected before any server call.
Source
Thrown at agents/drivers/zookeeper/operations.go:100
"found": true,
"key": path,
"value": encodeValue(data),
"metadata": statMetadata(stat),
}, nil
}
func (service *server) put(params json.RawMessage) (map[string]any, error) {
client, err := service.requireClient()
if err != nil {
return nil, err
}
var request putRequest
if err := json.Unmarshal(params, &request); err != nil {
return nil, err
}
path := normalizePath(request.Key)
if path == "/" {
return nil, errors.New("Root znode cannot be modified")
}
data, err := decodeValue(request.Value)
if err != nil {
return nil, err
}
writeMode := request.WriteMode
if writeMode == "" {
writeMode = "upsert"
}
switch writeMode {
case "create":
return createNode(client, path, data, request.CreateMode)
case "update":
stat, err := client.Set(path, data)
if err != nil {
return nil, err
}
return putResult(stat), nilView on GitHub (pinned to c0390bff16)
Solutions
- Provide a non-root key, e.g. "/myapp/config" instead of "/".
- Guard your caller code to reject empty or "/" keys before invoking put.
- Check how the key is assembled (prefix + name) — an unset prefix/name variable often collapses the path to "/".
- Remember ZooKeeper namespaces are hierarchical: pick a dedicated parent znode for application data.
Example fix
// before
if key == "" { key = "/" }
err := driver.Put(ctx, key, value)
// after
if key == "" { return fmt.Errorf("key must not be empty") }
err := driver.Put(ctx, "/myapp/"+key, value) Defensive patterns
Strategy: validation
Validate before calling
func validatePutKey(key string) error {
k := strings.TrimSpace(key)
if k == "" || k == "/" {
return errors.New("zookeeper put key must identify a non-root znode")
}
return nil
} Try / catch
if err := validatePutKey(key); err != nil { return err }
_, err := driver.Put(ctx, key, value)
if err != nil && strings.Contains(err.Error(), "Root znode cannot be modified") {
return fmt.Errorf("refusing to write znode root; supply a child path: %w", err)
} Prevention
- Never default an empty key to "/"
- Build keys with path.Join so prefixes cannot collapse to "/"
- Reject empty key fields at the API/config boundary
- Dedicate a namespace parent znode for application data
When it happens
Trigger: Calling put (directly or via dispatch) with Key = "/" or an empty/blank key that normalizePath resolves to "/". Raised in agents/drivers/zookeeper/operations.go:100.
Common situations: Empty key field in a JSON put request; key built by string concatenation where the prefix variable was empty ("" + "/" remaining as "/"); users intending 'the namespace root' and passing "/"; path-join bugs trimming the actual node name.
Related errors
- Root znode cannot be deleted
- Unsupported createMode: %s
- ZooKeeper server list is empty
- ZooKeeper auth scheme and credentials must be configured tog
- Unsupported auth_scheme %q; expected %q or %q
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/408a0ea4b249f567.
Report an issue: GitHub.