dgraph-io/dgraph · error

Node with %q cant have child attr

Error message

Node with %q cant have child attr

What it means

Aggregator functions (min, max, sum, avg, count) and password verifiers produce a single scalar value per node, so the node carrying such a function cannot have child attributes. treeCopy rejects any gchild whose Func.IsAggregator() or IsPasswordVerifier() and also has children. Children under an aggregate node have no meaningful output location.

Source

Thrown at query/query.go:622

			return errors.Errorf("Cannot specify order at both args and facets")
		}

		dst := &SubGraph{
			Attr:   gchild.Attr,
			Params: args,
		}
		if gchild.MathExp != nil {
			mathExp := &mathTree{}
			if err := mathCopy(mathExp, gchild.MathExp); err != nil {
				return err
			}
			dst.MathExp = mathExp
		}

		if gchild.Func != nil &&
			(gchild.Func.IsAggregator() || gchild.Func.IsPasswordVerifier()) {
			if len(gchild.Children) != 0 {
				return errors.Errorf("Node with %q cant have child attr", gchild.Func.Name)
			}
			// embedded filter will cause ambiguous output like following,
			// director.film @filter(gt(initial_release_date, "2016")) {
			//    min(initial_release_date @filter(gt(initial_release_date, "1986"))
			// }
			if gchild.Filter != nil {
				return errors.Errorf(
					"Node with %q cant have filter, please place the filter on the upper level",
					gchild.Func.Name)
			}
			if gchild.Func.Attr == "uid" {
				return errors.Errorf(`Argument cannot be "uid"`)
			}
			dst.createSrcFunction(gchild.Func)
		}

		if gchild.Filter != nil {
			dstf := &SubGraph{}

View on GitHub (pinned to 759e242be6)

Solutions

  1. Make the aggregate node a leaf: `min(friend)` or place the aggregate on a scalar predicate like `min(score)`
  2. Fetch child details in a sibling level, e.g. `friend { name }` alongside `min(...) as ...`
  3. For per-child aggregation, put the aggregator one level down on the scalar predicate: `friend { min(score) }`

Example fix

// before
{
  me(func: uid(0x1)) {
    min(friend) {
      name
    }
  }
}
// after
{
  me(func: uid(0x1)) {
    friend {
      name
    min as min(score)
    }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

function assertAggregateIsLeaf(node) {
  if (/^(min|max|sum|avg|count)\s*\(/.test(node.field) && node.children && node.children.length > 0) {
    throw new Error('Aggregator node cannot have child attributes');
  }
}

Type guard

const isAggregateWithChildren = (n) => n.func && ['min','max','sum','avg','count','checkpwd'].includes(n.func.name) && n.children && n.children.length > 0;

Try / catch

try {
  await txn.query(q);
} catch (e) {
  if (e.message.includes('cant have child attr')) {
    throw new Error('Make the aggregate node a leaf; fetch details in a sibling level');
  }
  throw e;
}

Prevention

When it happens

Trigger: Writing `min(friend) { name }` or `checkpwd(password) { ... }` with a brace block; query builders that always emit children for every field.

Common situations: Users trying to compute an aggregate of child values and also read child data in one node; misunderstanding that min(parent) aggregates the parent's child values, not a subtree query.

Related errors


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