cayleygraph/cayley · error
expected one predicate or path for recursive follow
Error message
expected one predicate or path for recursive follow
What it means
FollowRecursive requires exactly one predicate or path to follow recursively; if toViaDepthData yields more than one predicate, the method rejects the call with this error (errNoVia is used for zero). Recursion needs a single, unambiguous edge (or path) to traverse repeatedly up to maxDepth.
Source
Thrown at query/gizmo/traversals.go:260
return p.follow(path, true)
}
// FollowRecursive is the same as Follow but follows the chain recursively.
//
// Starts as if at the g.M() and follows through the morphism path multiple times, returning all nodes encountered.
//
// Example:
// // javascript:
// var friend = g.Morphism().out("<follows>")
// // Returns all people in Charlie's network.
// // Returns bob and dani (from charlie), fred (from bob) and greg (from dani).
// g.V("<charlie>").followRecursive(friend).all()
func (p *pathObject) FollowRecursive(call goja.FunctionCall) goja.Value {
preds, maxDepth, tags, ok := toViaDepthData(exportArgs(call.Arguments))
if !ok || len(preds) == 0 {
return throwErr(p.s.vm, errNoVia)
} else if len(preds) != 1 {
return throwErr(p.s.vm, fmt.Errorf("expected one predicate or path for recursive follow"))
}
np := p.clonePath()
np = np.FollowRecursive(preds[0], maxDepth, tags)
return p.newVal(np)
}
// And is an alias for Intersect.
func (p *pathObject) And(path *pathObject) *pathObject {
return p.Intersect(path)
}
// Intersect filters all paths by the result of another query path.
//
// This is essentially a join where, at the stage of each path, a node is shared.
// Example:
// // javascript
// var cFollows = g.V("<charlie>").Out("<follows>")
// var dFollows = g.V("<dani>").Out("<follows>")View on GitHub (pinned to 81dcd7d73e)
Solutions
- Pass a single predicate: p.followRecursive("knows").
- To follow several edge types, issue one followRecursive call per predicate and merge results.
- Or build a single path that encodes the multi-hop relation and pass that path as the sole argument.
Example fix
// before
p.followRecursive("knows", "likes", 3)
// after
p.followRecursive("knows", 3) Defensive patterns
Strategy: validation
Validate before calling
if (Array.isArray(preds) && preds.length > 1) throw new Error('followRecursive accepts exactly one predicate or path'); Type guard
function isSingleVia(args) { return args.length === 1 || (args.length === 2 && typeof args[1] === 'number'); } Try / catch
try { p.followRecursive(preds, depth); } catch (e) { if (String(e).includes('expected one predicate')) { /* split per predicate */ } throw e; } Prevention
- Call followRecursive once per relationship type
- Combine multiple edges into a single path when possible
- Remember recursion requires a single unambiguous edge
When it happens
Trigger: Calling p.followRecursive(["knows","likes"]) or followRecursive(pred1, pred2, maxDepth) — any call where the resolved preds slice has length > 1 at query/gizmo/traversals.go:260.
Common situations: Scripts attempting to follow multiple relationship types recursively in one call, expecting OR semantics that the API does not provide.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- must specify a tag name when saving a path
- invalid argument type in filter()
- expected string, got: %T
- unsupported type: %T
- errNoVia
AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06).
Data as JSON: /api/errors/bc92e3970b7f2d8a.
Report an issue: GitHub.