dgraph-io/dgraph · error

Vars can be assigned only when grouped by UID attribute

Error message

Vars can be assigned only when grouped by UID attribute

What it means

When filling a groupby-exported variable, fillGroupedVars type-asserts the single group key value to uint64 (a UID). If the grouped attribute is not a UID (e.g. a string or int predicate), the variable cannot be keyed by UID, so the query is rejected.

Source

Thrown at query/groupby.go:348

			}
		}
		if child.Params.Var == "" {
			continue
		}
		chVar := child.Params.Var

		tempMap := types.NewShardedMap()
		for _, grp := range res.group {
			if len(grp.keys) == 0 {
				continue
			}
			if len(grp.keys) > 1 {
				return errors.Errorf("Expected one UID for var in groupby but got: %d", len(grp.keys))
			}
			uidVal := grp.keys[0].key.Value
			uid, ok := uidVal.(uint64)
			if !ok {
				return errors.Errorf("Vars can be assigned only when grouped by UID attribute")
			}
			// grp.aggregates could be empty if schema conversion failed during aggregation
			if len(grp.aggregates) > 0 {
				tempMap.Set(uid, grp.aggregates[len(grp.aggregates)-1].key)
			}
		}
		doneVars[chVar] = varValue{
			Vals: tempMap,
			path: append(path, pathNode),
		}
	}
	return nil
}

func (sg *SubGraph) processGroupBy(doneVars map[string]varValue, path []*SubGraph) error {
	for _, ul := range sg.uidMatrix {
		// We need to process groupby for each list as grouping needs to happen for each path of the
		// tree.

View on GitHub (pinned to 759e242be6)

Solutions

  1. Change the groupby attribute to uid (or another UID-valued predicate) so the exported variable can be keyed by UID
  2. Remove the AS export and use plain aggregation inside groupby without reusing the variable elsewhere
  3. Compute the aggregate with a separate @groupby/sum query structure that does not bind variables

Example fix

// before
{
  users(func: type(User)) {
    groupby(name) {
      total as count(posts)
    }
  }
}
// after
{
  users(func: type(User)) {
    groupby(uid) {
      total as count(posts)
    }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the groupby attribute is UID-valued when exporting a variable:
function validateGroupbyAttrIsUid(attr, exportsVar) {
  if (exportsVar && attr !== 'uid') {
    throw new Error('Vars can only be exported when grouped by uid');
  }
}

Try / catch

try {
  const res = await dgraph.newTxn().query(query);
} catch (e) {
  if (String(e).includes('grouped by UID attribute')) {
    // rewrite query to groupby(uid) or drop the AS export
  } else throw e;
}

Prevention

When it happens

Trigger: `AS` variable export inside groupby where the grouped key is a non-UID attribute (e.g. groupby(name) with total as sum(x)), so grp.keys[0].key.Value is not uint64.

Common situations: Grouping on a string predicate while exporting an aggregate variable; assuming variables work with any groupby attribute; copying a uid-grouped template and swapping the attribute.

Related errors


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