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. If

View on GitHub (pinned to 759e242be6)

Solutions

  1. Narrow the destination variable to a single node with a unique filter (eq on unique predicate, or first: 1)
  2. Replace var(t) with a literal UID when the destination is known
  3. Verify the emitting clause alone returns exactly one node
  4. 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

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


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