dgraph-io/dgraph · error
Variable not found in math
Error message
Variable not found in math
What it means
MathTree.subs substitutes query variables (names starting with `$`) in a math expression tree with their concrete values using the provided varMap. This error is thrown when a `$var` referenced in a math() block is not present in the variable map, i.e. the variable was never defined by an earlier query clause. The library cannot evaluate the expression without it, so it fails fast.
Source
Thrown at dql/math.go:351
if valueStack.empty() {
// This happens when we have math(). We can either return an error or
// ignore. Currently, let's just ignore and pretend there is no expression.
return nil, false, errors.Errorf("Empty () not allowed in math block.")
}
if valueStack.size() != 1 {
return nil, false, errors.Errorf("Expected one item in value stack, but got %d",
valueStack.size())
}
res, err := valueStack.pop()
return res, false, err
}
func (t *MathTree) subs(vmap varMap) error {
if strings.HasPrefix(t.Var, "$") {
va, ok := vmap[t.Var]
if !ok {
return errors.Errorf("Variable not found in math")
}
var err error
t.Const, err = parseValue(va)
if err != nil {
return err
}
t.Var = ""
}
for _, i := range t.Child {
if err := i.subs(vmap); err != nil {
return err
}
}
return nil
}
// debugString converts mathTree to a string. Good for testing, debugging.
// nolint: unusedView on GitHub (pinned to 759e242be6)
Solutions
- Define the variable before the math block, e.g. add a clause like `countOfFriends as count(friend)` so `$countOfFriends` exists in the var map.
- Check for case/typo mismatches between the `$name` used in math() and the name emitted by the defining clause.
- If the query was split into parts, re-join it so variable-producing clauses execute in the same request.
- Wrap the math expression in a guard (e.g. math($var == nil ? 0 : ...)) only if the version supports nil checks; otherwise provide a default value clause.
Example fix
// before
{
me(func: uid(0x1)) {
val(score) // $score never defined
f as math($score * 2)
}
}
// after
{
var(func: uid(0x1)) {
friend {
score as math(1)
}
s as sum(val(score))
}
me(func: uid(0x1)) {
f as math($s * 2)
}
} Defensive patterns
Strategy: validation
Validate before calling
func hasVarDef(query, varName string) bool {
// varName like "score"; look for 'as ...' clause producing it before use
return strings.Contains(query, varName+" as ") || strings.Contains(query, " as "+varName)
}
// check every $var in math() has a corresponding 'X as ...' definition Try / catch
err := runQuery(txn, q)
if err != nil && strings.Contains(err.Error(), "Variable not found in math") {
return fmt.Errorf("query variable used in math() is not defined by any prior clause: %w", err)
} Prevention
- Define every $variable with an 'as' clause earlier in the same query.
- Keep variable names consistent (Dgraph variables are case-sensitive).
- After refactoring queries, grep for remaining $vars and verify their defining clauses still exist.
When it happens
Trigger: A DQL query contains `math($someVar ...)` but no prior query node defines `someVar as *someVar` (variable not bound), so vmap lookup for "$someVar" misses.
Common situations: Typos in variable names (case mismatch: `$count` vs `$Count`), restructuring a query and removing the clause that emitted the variable, or running a sub-query standalone that depended on variables from a parent query.
Related errors
- Invalid Math expression
- Invalid math statement. Expected 1 operands
- Division by zero
- Invalid Math expression. Expected 3 operands
- Invalid Math expression. Expected 2 operands
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/4e9b68c3243b516f.
Report an issue: GitHub.