cayleygraph/cayley · error
did not pass a string predicate or a Path to FollowRecursive
Error message
did not pass a string predicate or a Path to FollowRecursive
What it means
FollowRecursive accepts either a string predicate or a *Path describing the traversal to repeat recursively. Any other argument (nil, an unsupported wrapper type, etc.) falls into the default case of the type switch and panics, since no recursive traversal can be built from it.
Source
Thrown at query/path/path.go:396
// If 0 is passed, it will use the default value of 50 steps before returning.
// If 1 is passed, it will stop after 1 step before returning, and so on.
//
// The third argument, "depthTags" is a set of tags that will return strings of
// numeric values relating to how many applications of the path were applied the
// first time the result node was seen.
//
// This is a very expensive operation in practice. Be sure to use it wisely.
func (p *Path) FollowRecursive(via interface{}, maxDepth int, depthTags []string) *Path {
var path *Path
switch v := via.(type) {
case string:
path = StartMorphism().Out(v)
case quad.Value:
path = StartMorphism().Out(v)
case *Path:
path = v
default:
panic("did not pass a string predicate or a Path to FollowRecursive")
}
np := p.clone()
np.stack = append(p.stack, followRecursiveMorphism(path, maxDepth, depthTags))
return np
}
// Save will, from the current nodes in the path, retrieve the node
// one linkage away (given by either a path or a predicate), add the given
// tag, and propagate that to the result set.
//
// For example:
// // Will return []map[string]string{{"social_status: "cool"}}
// StartPath(qs, "B").Save("status", "social_status"
func (p *Path) Save(via interface{}, tag string) *Path {
np := p.clone()
np.stack = append(np.stack, saveMorphism(via, tag))
return np
}View on GitHub (pinned to 81dcd7d73e)
Solutions
- Pass the predicate name as a string, e.g. p.FollowRecursive("dependsOn", 10, nil).
- Pass a *Path built with StartMorphism()/StartPath, e.g. p.FollowRecursive(cayley.StartMorphism().Out("dependsOn"), 10, nil).
- Validate the argument is non-nil and of an accepted type before calling.
Example fix
// before
var predicate string // left nil
p.FollowRecursive(predicate, 5, nil) // panics
// after
p.FollowRecursive("dependsOn", 5, nil) Defensive patterns
Strategy: type-guard
Validate before calling
func validFollowArg(v interface{}) bool {
switch v.(type) {
case string, *path.Path:
return true
default:
return false
}
}
if !validFollowArg(arg) {
return errors.New("FollowRecursive needs a string predicate or a *Path")
} Type guard
switch v.(type) { case string, *path.Path: return true }; return false Try / catch
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("FollowRecursive failed: %v", r)
}
}() Prevention
- Only pass string or *Path to FollowRecursive.
- Check for nil/zero-valued variables before building recursive paths.
- recover() around query construction in scripts.
When it happens
Trigger: Calling path.FollowRecursive(arg, maxDepth, depthTags) where arg is neither a string nor a *Path — typically a nil interface or a value of the wrong type.
Common situations: Passing a helper result typed interface{} instead of string/*Path; an unassigned (nil) predicate variable; passing node values from a different API layer.
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
- not implemented
- not implemented: need a function from predicates to their as
- Building an iterator from a morphism. Bind a QuadStore with
- unexpected type for int field: %T
- unexpected type for pb field: %T
AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06).
Data as JSON: /api/errors/68ad5cb49369220e.
Report an issue: GitHub.