dgraph-io/dgraph · error
to variable(%s) should only expand to 1 uid
Error message
to variable(%s) should only expand to 1 uid
What it means
The 'to' endpoint of a shortest-path query must resolve to exactly one node. When supplied via a variable, Dgraph checks the variable's UID list length and throws this error if it contains more than one UID, since a path to multiple destinations is ambiguous.
Source
Thrown at query/query.go:1796
}
if uidVar.Uids != nil && len(uidVar.Uids.Uids) > 0 {
if len(uidVar.Uids.Uids) > 1 {
return errors.Errorf("from variable(%s) should only expand to 1 uid", fromVar)
}
sg.Params.From = uidVar.Uids.Uids[0]
}
}
if sg.Params.ShortestPathArgs.To != nil && len(sg.Params.ShortestPathArgs.To.NeedsVar) > 0 {
toVar := sg.Params.ShortestPathArgs.To.NeedsVar[0].Name
uidVar, ok := mp[toVar]
if !ok {
return errors.Errorf("value of to var(%s) should have already been populated",
toVar)
}
if uidVar.Uids != nil && len(uidVar.Uids.Uids) > 0 {
if len(uidVar.Uids.Uids) > 1 {
return errors.Errorf("to variable(%s) should only expand to 1 uid", toVar)
}
sg.Params.To = uidVar.Uids.Uids[0]
}
}
return nil
}
// fillVars reads the value corresponding to a variable from the map mp and stores it inside
// SubGraph. This value is then later used for execution of the SubGraph.
func (sg *SubGraph) fillVars(mp map[string]varValue) error {
if sg.Params.Alias == "shortest" {
if err := sg.fillShortestPathVars(mp); err != nil {
return err
}
}
var lists []*pb.List
// Go through all the variables in NeedsVar and see if we have a value for them in the map. IfView on GitHub (pinned to 759e242be6)
Solutions
- Narrow the destination variable to a single node with a unique filter (eq on unique predicate, or first: 1)
- Replace var(t) with a literal UID when the destination is known
- Verify the emitting clause alone returns exactly one node
- Split the query if multiple destination paths are genuinely needed (one shortest per destination)
Example fix
// before: multiple destinations
t as var(func: eq(type, "Person"))
p(func: uid(0x1)) { shortest(to: var(t)) { uid } }
// after: single destination
t as var(func: eq(email, "bob@example.com"))
p(func: uid(0x1)) { shortest(to: var(t)) { uid } } Defensive patterns
Strategy: validation
Validate before calling
if countNodes(toEmittingClause) != 1 {
return fmt.Errorf("to-variable must resolve to exactly one node")
} Try / catch
if err != nil && strings.Contains(err.Error(), "should only expand to 1 uid") && strings.Contains(err.Error(), "to") {
return fmt.Errorf("to-variable ambiguous; narrow the filter: %w", err)
} Prevention
- Use a unique predicate filter for the destination variable
- Add first: 1 to force a single destination
- Run one shortest-path query per destination when multiple targets are needed
When it happens
Trigger: shortest(..., to: var(t)) where var(t) matched multiple nodes, e.g. 't as var(func: eq(type, "Person"))' returning several UIDs, or a variable accumulated UIDs across multiple matches.
Common situations: Overly broad filter on the destination variable; variable reused from a list-producing clause; expecting implicit first-node selection.
Related errors
- value of from var(%s) should have already been populated
- from variable(%s) should only expand to 1 uid
- value of to var(%s) should have already been populated
- from/to can't be nil for shortest path
- Invalid variable aggregation. Check the levels.
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/75c73671776ad78a.
Report an issue: GitHub.