gastownhall/beads · error · publicops.ErrValidation
max rows must not be negative, got %d
Error message
max rows must not be negative, got %d
What it means
ValidateWalkTreeRequest rejects a negative MaxRows with this ErrValidation-wrapped error. The library throws it because a negative row cap is meaningless for a result-limiting field; use 0 (treated as the library's no-limit/default) or a positive cap.
Source
Thrown at internal/storage/issueops/tree_walk.go:44
if req.RootID == "" {
return "", fmt.Errorf("%w: root id must not be empty", publicops.ErrValidation)
}
direction := req.Direction
if direction == "" {
direction = publicops.TreeDown
}
switch direction {
case publicops.TreeDown, publicops.TreeUp, publicops.TreeBoth:
default:
return "", fmt.Errorf("%w: direction %q must be one of %q, %q, %q",
publicops.ErrValidation, req.Direction,
publicops.TreeDown, publicops.TreeUp, publicops.TreeBoth)
}
if req.MaxDepth < 1 {
return "", fmt.Errorf("%w: max depth must be at least 1, got %d", publicops.ErrValidation, req.MaxDepth)
}
if req.MaxRows < 0 {
return "", fmt.Errorf("%w: max rows must not be negative, got %d", publicops.ErrValidation, req.MaxRows)
}
return direction, nil
}
// PruneTreeByStatus keeps every node carrying status, plus the ancestor chain of
// each survivor, in the walk order the nodes arrived in.
//
// KEEPING THE ANCESTORS IS WHAT MAKES THE ANSWER STILL A TREE. A bare filter
// would return nodes whose ParentID names something absent from the answer, and
// every renderer that rebuilds the shape from Depth and ParentID would then draw
// orphans at the wrong indentation.
//
// A PRUNE THAT MATCHES NOTHING RETURNS NOTHING, root included. The root survives
// only as somebody's ancestor, never for its own sake, so a tree with no
// matching member comes back empty rather than as a lone root — see
// issueops.WalkTreeRequest.Status, which states it as a promise.
func PruneTreeByStatus(nodes []*types.TreeNode, status types.Status) []*types.TreeNode {
if len(nodes) == 0 {View on GitHub (pinned to 71377f2769)
Solutions
- Set req.MaxRows to 0 to mean unlimited, or a positive integer to cap results.
- Clamp computed values: if maxRows < 0 { maxRows = 0 }.
- Update code that uses the -1-as-unlimited convention to this library's 0-means-unlimited convention.
Example fix
// before req.MaxRows = -1 // "unlimited" // after req.MaxRows = 0 // 0 means no row limit
Defensive patterns
Strategy: validation
Validate before calling
if req.MaxRows < 0 {
req.MaxRows = 0
} Try / catch
if err := walk(ctx, req); errors.Is(err, publicops.ErrValidation) {
// fix MaxRows; validation errors are not retryable as-is
} Prevention
- Normalize limit fields at construction time (negative -> 0).
- Centralize request-building in one helper so clamping is applied consistently.
- Document the 0-means-unlimited convention so -1 is not reintroduced.
When it happens
Trigger: Calling WalkDependencyTreeInTx with req.MaxRows < 0, e.g. -1 used as an "unlimited" sentinel carried over from a different API's convention.
Common situations: Using -1 for "no limit" per another library's convention; computing MaxRows via subtraction that can go negative; misparsed config values.
Related errors
- max depth must be at least 1, got %d
- direction %q must be one of %q, %q, %q
- no store is open for this workspace
- not found
- no absolute native user directory is available
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/a244757451842f49.
Report an issue: GitHub.