{"record":{"id":"0cedc2519b0c2347","repo":"dgraph-io/dgraph","slug":"count-predicate-cannot-be-used-to-search-for-nega","errorCode":null,"errorMessage":"count(predicate) cannot be used to search for negative counts (nonsensical) or zero counts (not tracked).","messagePattern":"count\\(predicate\\) cannot be used to search for negative counts \\(nonsensical\\) or zero counts \\(not tracked\\)\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"worker/task.go","lineNumber":2532,"sourceCode":"\tvar illegal bool\n\tswitch cp.fn {\n\tcase \"eq\":\n\t\tillegal = countl <= 0\n\tcase \"lt\":\n\t\tillegal = countl <= 1\n\tcase \"le\":\n\t\tillegal = countl <= 0\n\tcase \"gt\":\n\t\tillegal = countl < 0\n\tcase \"ge\":\n\t\tillegal = countl <= 0\n\tcase \"between\":\n\t\tillegal = countl <= 0 || counth <= 0\n\tdefault:\n\t\tx.AssertTruef(false, \"unhandled count comparison fn: %v\", cp.fn)\n\t}\n\tif illegal {\n\t\treturn errors.Errorf(\"count(predicate) cannot be used to search for \" +\n\t\t\t\"negative counts (nonsensical) or zero counts (not tracked).\")\n\t}\n\n\tcountKey := x.CountKey(cp.attr, uint32(countl), cp.reverse)\n\tif cp.fn == \"eq\" {\n\t\tpl, err := qs.cache.GetUids(countKey)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tuids, err := pl.Uids(posting.ListOptions{ReadTs: cp.readTs})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tout.UidMatrix = append(out.UidMatrix, uids)\n\t\treturn nil\n\t}\n\n\tswitch cp.fn {","sourceCodeStart":2514,"sourceCodeEnd":2550,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/task.go#L2514-L2550","documentation":"count(predicate) filters in Dgraph only support searching for positive counts, because zero and negative facet/edge counts are not indexed. An `illegal` flag is set based on the comparison function and bounds; if the request asks for counts <= 0, the query errors out.","triggerScenarios":"Queries like has(pred) @filter(count(f) == 0), count(f) < 1, count(f) <= 0, or between with bounds <= 0 — anything that logically requires matching zero or negative counts.","commonSituations":"Trying to find nodes with no edges of a predicate via count == 0; off-by-one bounds from generated UIs; assuming absence is indexed.","solutions":["Replace count == 0 / < 1 checks with filter NOT has(<pred>) or has(<pred>) negation to find nodes without the predicate.","Use count >= 1 (or gt 0 via ge(count,1)) instead of <= 0 comparisons.","Clamp `between` bounds to >= 1 in application code before issuing the query."],"exampleFix":"// before\n{\n  q(func: type(Person)) @filter(count(friend) == 0)\n}\n// after\n{\n  q(func: type(Person)) @filter(NOT has(friend))\n}","handlingStrategy":"validation","validationCode":"function validateCountFilter(fn, l, h) {\n  if (l <= 0 || (fn === \"between\" && h <= 0))\n    throw new Error(\"count(predicate) only supports positive counts; use NOT has(pred) for zero\");\n}\nvalidateCountFilter(\"ge\", countLow, countHigh);","typeGuard":null,"tryCatchPattern":"try {\n  return await txn.query(query);\n} catch (e) {\n  if (/negative counts|zero counts/.test(String(e))) {\n    // rewrite to NOT has(pred) and retry\n  }\n  throw e;\n}","preventionTips":["Never query count == 0 or count < 1; use NOT has(pred).","Clamp between bounds to >= 1 in app code.","Remember zero counts are not indexed in Dgraph."],"tags":["dgraph","query","count","filter"],"backgroundTag":"unindexed-zero-count-query","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}