dgraph-io/dgraph · error

count(predicate) cannot be used to search for negative count

Error message

count(predicate) cannot be used to search for negative counts (nonsensical) or zero counts (not tracked).

What it means

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.

Source

Thrown at worker/task.go:2532

	var illegal bool
	switch cp.fn {
	case "eq":
		illegal = countl <= 0
	case "lt":
		illegal = countl <= 1
	case "le":
		illegal = countl <= 0
	case "gt":
		illegal = countl < 0
	case "ge":
		illegal = countl <= 0
	case "between":
		illegal = countl <= 0 || counth <= 0
	default:
		x.AssertTruef(false, "unhandled count comparison fn: %v", cp.fn)
	}
	if illegal {
		return errors.Errorf("count(predicate) cannot be used to search for " +
			"negative counts (nonsensical) or zero counts (not tracked).")
	}

	countKey := x.CountKey(cp.attr, uint32(countl), cp.reverse)
	if cp.fn == "eq" {
		pl, err := qs.cache.GetUids(countKey)
		if err != nil {
			return err
		}
		uids, err := pl.Uids(posting.ListOptions{ReadTs: cp.readTs})
		if err != nil {
			return err
		}
		out.UidMatrix = append(out.UidMatrix, uids)
		return nil
	}

	switch cp.fn {

View on GitHub (pinned to 759e242be6)

Solutions

  1. Replace count == 0 / < 1 checks with filter NOT has(<pred>) or has(<pred>) negation to find nodes without the predicate.
  2. Use count >= 1 (or gt 0 via ge(count,1)) instead of <= 0 comparisons.
  3. Clamp `between` bounds to >= 1 in application code before issuing the query.

Example fix

// before
{
  q(func: type(Person)) @filter(count(friend) == 0)
}
// after
{
  q(func: type(Person)) @filter(NOT has(friend))
}
Defensive patterns

Strategy: validation

Validate before calling

function validateCountFilter(fn, l, h) {
  if (l <= 0 || (fn === "between" && h <= 0))
    throw new Error("count(predicate) only supports positive counts; use NOT has(pred) for zero");
}
validateCountFilter("ge", countLow, countHigh);

Try / catch

try {
  return await txn.query(query);
} catch (e) {
  if (/negative counts|zero counts/.test(String(e))) {
    // rewrite to NOT has(pred) and retry
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: Trying to find nodes with no edges of a predicate via count == 0; off-by-one bounds from generated UIs; assuming absence is indexed.

Related errors


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