cayleygraph/cayley · error
must specify a tag name when saving a path
Error message
must specify a tag name when saving a path
What it means
In the Gizmo (Gremlin-like) query language, Save(via) stores the reached value under a tag. When the "via" argument is a path object (a subquery) rather than a plain value, the tag name becomes mandatory because it can no longer be inferred from a literal predicate/vertex string. If the tag string is empty in that case, the VM aborts with this error.
Source
Thrown at query/gizmo/traversals.go:468
}
func (p *pathObject) save(call goja.FunctionCall, rev, opt bool) goja.Value {
args := exportArgs(call.Arguments)
if len(args) > 2 || len(args) == 0 {
return throwErr(p.s.vm, errArgCount{Got: len(args)})
}
var vtag interface{} = ""
if len(args) == 2 {
vtag = args[1]
}
tag, ok := vtag.(string)
if !ok {
return throwErr(p.s.vm, fmt.Errorf("expected string, got: %T", vtag))
}
via := args[0]
if vp, ok := via.(*pathObject); ok {
via = vp.path
if tag == "" {
return throwErr(p.s.vm, errors.New("must specify a tag name when saving a path"))
}
} else {
qv, err := toQuadValue(via)
via = qv
if err != nil {
return throwErr(p.s.vm, err)
}
if tag == "" {
if p.s.col == query.JSONLD {
switch qv := qv.(type) {
case quad.IRI:
tag = string(qv)
case quad.String:
tag = string(qv)
default:
tag = quad.StringOf(qv)
}
} else {View on GitHub (pinned to 81dcd7d73e)
Solutions
- Provide a non-empty tag string as the second argument: g.Save(g.V("foo").Out(), "myTag").
- If you meant to save a literal predicate value, pass the string directly (tag can stay implicit for string via): g.Save("pred", "tag").
- Review SaveR/SaveOpt/SaveOptR call sites for an empty-string tag when via is a path.
- Validate tag names when generating Gizmo queries from templates or code.
Example fix
// before
it := g.Save(g.V("status").Out("followers"), "")
// after
it := g.Save(g.V("status").Out("followers"), "followersTag") Defensive patterns
Strategy: validation
Validate before calling
function savePath(pathObj, tag) {
if (pathObj instanceof g.Path && (!tag || typeof tag !== "string")) {
throw new Error("Save with a path via requires a non-empty tag string");
}
return g.Save(pathObj, tag);
} Type guard
function isPathObject(v) { return v != null && typeof v === "object" && typeof v.ToArray === "function"; }
// if isPathObject(via) and tag === "" -> Save will fail; require a tag Try / catch
try {
result = g.Save(via, tag).Iterate();
} catch (e) {
if (e.message.includes("must specify a tag name")) {
throw new Error("Save(path, tag) requires a non-empty tag; supply one for via=" + via);
}
throw e;
} Prevention
- Always pass an explicit tag when the via argument is a path (g.V().Out(), etc.).
- Only omit/empty the tag when via is a literal string value.
- Lint generated Gizmo queries for Save(..., "") patterns.
When it happens
Trigger: Calling g.Save(<pathObject>, "") or SaveR/SaveOpt/SaveOptR with a path as the via argument and an empty tag string. E.g. g.Save(g.V("foo").Out(), "") — a path via with no tag.
Common situations: Copy-pasting Save calls where the first form used a string predicate (tag optional) and later swapping in a path; building queries programmatically and leaving the tag empty; misunderstanding that a tag is optional only when via is a literal value.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- errNoVia
- invalid argument type in filter()
- expected string, got: %T
- unsupported type: %T
- expected one predicate or path for recursive follow
AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06).
Data as JSON: /api/errors/dc72668b9421507e.
Report an issue: GitHub.