t8y2/dbx · error
Continuation does not match request
Error message
Continuation does not match request
What it means
listPrefix supports cursor-based pagination. A continuation token encodes the root path and whether listing is recursive (via decodeCursor). If the decoded cursor's Root or Recursive flag differs from the current request, the token cannot be applied to this query and 'Continuation does not match request' is returned.
Source
Thrown at agents/drivers/zookeeper/operations.go:292
return listResponse{}, err
}
root := normalizePath(request.Prefix)
recursive := true
if request.Recursive != nil {
recursive = *request.Recursive
}
limit := request.Limit
if limit < 1 {
limit = defaultListLimit
}
cursor := listCursor{Root: root, Recursive: recursive}
if strings.TrimSpace(request.Continuation) != "" {
decoded, err := decodeCursor(request.Continuation)
if err != nil {
return listResponse{}, err
}
if decoded.Root != root || decoded.Recursive != recursive {
return listResponse{}, errors.New("Continuation does not match request")
}
cursor = decoded
}
exists, _, err := client.Exists(root)
if err != nil {
return listResponse{}, err
}
if !exists {
return listResponse{Keys: []map[string]any{}, Continuation: nil}, nil
}
var paths []string
if recursive {
paths, err = listRecursive(client, root)
} else {
paths, err = listDirectChildren(client, root)
}
if err != nil {
return listResponse{}, errView on GitHub (pinned to c0390bff16)
Solutions
- Restart listing from the first page with the new parameters instead of passing the old continuation.
- Keep the root and Recursive flag identical across all pages of one listing loop.
- Generate a fresh token per listing session; never share tokens across different queries or users.
- If cursors are persisted client-side, include the request parameters alongside and discard the token when they change.
Example fix
// before // page 2 request changed Recursive from true to false but reused token cursor, err := driver.List(ctx, root, false, token) // after cursor, err := driver.List(ctx, root, true, token) // same params as page 1 // (or drop token: driver.List(ctx, root, false, ""))
Defensive patterns
Strategy: validation
Validate before calling
// Keep listing parameters stable across pages; reset the token when they change
func (p *Pager) TokenFor(root string, recursive bool) string {
if p.root != root || p.recursive != recursive {
return "" // parameters changed: start a fresh listing
}
return p.continuation
} Try / catch
resp, err := driver.List(ctx, root, recursive, token)
if err != nil && strings.Contains(err.Error(), "Continuation does not match request") {
token = "" // stale cursor: restart listing from the first page
resp, err = driver.List(ctx, root, recursive, token)
} Prevention
- Store root+recursive alongside the cursor and invalidate on change
- Never reuse continuation tokens across different list queries
- Generate fresh tokens per pagination session/user
- Handle parameter changes in UI by resetting pagination state
When it happens
Trigger: Calling listPrefix with a Continuation obtained from a different root path, or with a Recursive value different from the request that produced the token (e.g. token from a recursive list reused for a flat list, or from another prefix). Raised in agents/drivers/zookeeper/operations.go:292.
Common situations: Client-side pagination loop that changes the prefix or Recursive flag between pages; reusing a stored cursor after the user changed search parameters; mixing cursors between two concurrent lists; serialization bugs truncating/corrupting the cursor (though that usually errors in decodeCursor first).
Related errors
- {process.candidate.name} paged query returned {rows} rows, e
- ZooKeeper server list is empty
- ZooKeeper auth scheme and credentials must be configured tog
- Unsupported auth_scheme %q; expected %q or %q
- base_sleep_time_ms must be non-negative
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/368c6b82ce1fc23a.
Report an issue: GitHub.