{"record":{"id":"84a71b85ede0845b","repo":"dgraph-io/dgraph","slug":"invalid-math-expression-expected-3-operands","errorCode":null,"errorMessage":"Invalid Math expression. Expected 3 operands","messagePattern":"Invalid Math expression\\. Expected 3 operands","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"dql/math.go","lineNumber":124,"sourceCode":"\t}\n\tswitch {\n\tcase isUnary(topOp.Fn):\n\t\t// Since \"not\" is a unary operator, just pop one value.\n\t\ttopVal, err := valueStack.pop()\n\t\tif err != nil {\n\t\t\treturn errors.Errorf(\"Invalid math statement. Expected 1 operands\")\n\t\t}\n\t\tif opStack.size() > 1 {\n\t\t\tpeek := opStack.peek().Fn\n\t\t\tif (peek == \"/\" || peek == \"%\") && isZero(topOp.Fn, topVal.Const) {\n\t\t\t\treturn errors.Errorf(\"Division by zero\")\n\t\t\t}\n\t\t}\n\t\ttopOp.Child = []*MathTree{topVal}\n\n\tcase isTernary(topOp.Fn):\n\t\tif valueStack.size() < 3 {\n\t\t\treturn errors.Errorf(\"Invalid Math expression. Expected 3 operands\")\n\t\t}\n\t\ttopVal1 := valueStack.popAssert()\n\t\ttopVal2 := valueStack.popAssert()\n\t\ttopVal3 := valueStack.popAssert()\n\t\ttopOp.Child = []*MathTree{topVal3, topVal2, topVal1}\n\n\tdefault:\n\t\tif valueStack.size() < 2 {\n\t\t\treturn errors.Errorf(\"Invalid Math expression. Expected 2 operands\")\n\t\t}\n\t\tif isZero(topOp.Fn, valueStack.peek().Const) {\n\t\t\treturn errors.Errorf(\"Division by zero.\")\n\t\t}\n\t\ttopVal1 := valueStack.popAssert()\n\t\ttopVal2 := valueStack.popAssert()\n\t\ttopOp.Child = []*MathTree{topVal2, topVal1}\n\n\t}","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/dql/math.go#L106-L142","documentation":"Error returned by the DQL math parser (dql/math.go) when a math function that requires exactly 3 operands (e.g. logbase or pow-style ternary functions) is given a different number of arguments. Fix by passing exactly three operands to the math function.","triggerScenarios":"math(cond(a,b)) with only two arguments, math(cond()) with none, or an unbalanced comma causing cond to consume fewer values, e.g. missing nested parentheses around a sub-expression.","commonSituations":"Typos when writing conditional logic in aggregation math blocks; refactoring that dropped an argument; nested cond calls with mismatched commas: math(cond(a, cond(b, c, d))) miscounted.","solutions":["Provide all three arguments: math(cond(condition, valueIfTrue, valueIfFalse)).","Wrap nested sub-expressions in parentheses so each cond gets its own operand group.","Count commas: a cond at top level inside math must have exactly two commas.","Break complex nested cond expressions into intermediate variables (v as cond(...))."],"exampleFix":"// before\nu as math(cond(a, b))\n// after\nu as math(cond(a, b, 0))","handlingStrategy":"validation","validationCode":"// cond must have exactly two commas at its own paren level\nfunction validateCond(expr) {\n  const m = expr.match(/cond\\s*\\(([^()]*)\\)/);\n  if (!m) return true;\n  const commas = (m[1].match(/,/g) || []).length;\n  if (commas !== 2) throw new Error('cond needs exactly 3 arguments');\n  return true;\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await dgraph.query(query);\n} catch (err) {\n  if (/Expected 3 operands/.test(String(err))) {\n    throw new Error('cond() in math requires 3 arguments: cond(cond, ifTrue, ifFalse)');\n  }\n  throw err;\n}","preventionTips":["Always write cond with three arguments and two commas","Parenthesize nested sub-expressions passed to cond","Prefer intermediate variables for deeply nested conditionals","Unit-test math expressions before deploying query templates"],"tags":["dql","dgraph","cond","math-parser"],"backgroundTag":"invalid-math-expression","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}