dgraph-io/dgraph · error

from variable(%s) should only expand to 1 uid

Error message

from variable(%s) should only expand to 1 uid

What it means

Shortest-path queries require exactly one start node. When the 'from' endpoint comes from a variable, Dgraph checks that the variable resolves to at most one UID; if it expands to multiple UIDs the path is ambiguous and this error is thrown.

Source

Thrown at query/query.go:1781

}

// fillShortestPathVars reads value of the uid variable from mp map and fills it into From and To
// parameters.
func (sg *SubGraph) fillShortestPathVars(mp map[string]varValue) error {
	// The uidVar.Uids can be nil or have an empty uid list if the variable didn't
	// return any uids. This would mean sg.Params.From or sg.Params.To is 0 and the
	// query would return an empty result.

	if sg.Params.ShortestPathArgs.From != nil && len(sg.Params.ShortestPathArgs.From.NeedsVar) > 0 {
		fromVar := sg.Params.ShortestPathArgs.From.NeedsVar[0].Name
		uidVar, ok := mp[fromVar]
		if !ok {
			return errors.Errorf("value of from var(%s) should have already been populated",
				fromVar)
		}
		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]
		}

View on GitHub (pinned to 759e242be6)

Solutions

  1. Narrow the variable's query so it matches exactly one node (add a unique filter like eq(email, ...) or first: 1)
  2. Use a literal UID in shortest(from:) if the node is known
  3. Use a more specific predicate to disambiguate
  4. Inspect the variable's contents by running the emitting clause alone

Example fix

// before: matches many
f as var(func: eq(type, "Person"))
p(func: uid(0x1)) { shortest(from: var(f), to: 0x2) { uid } }
// after: exactly one
f as var(func: eq(email, "alice@example.com"))
p(func: uid(0x1)) { shortest(from: var(f), to: 0x2) { uid } }
Defensive patterns

Strategy: validation

Validate before calling

// Run the emitting clause first and assert it yields exactly one node
if countNodes(emittingClause) != 1 {
    return fmt.Errorf("from-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(), "from") {
    return fmt.Errorf("from-variable ambiguous; narrow the filter: %w", err)
}

Prevention

When it happens

Trigger: shortest(from: var(f), ...) where var(f) matched multiple nodes, e.g. 'f as var(func: eq(type, "Person"))' matching many people, or a uid variable accumulated multiple UIDs.

Common situations: Filter too broad in the variable-emitting clause; using a variable populated from a multi-result query; expecting Dgraph to pick a node automatically.

Related errors


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/962c8f2c42f414e0. Report an issue: GitHub.