dgraph-io/dgraph · error

Exceeded query edge limit = %v. Found %v edges.

Error message

Exceeded query edge limit = %v. Found %v edges.

What it means

Recurse queries expand outward from root nodes up to a depth. If the total number of edges traversed exceeds x.Config.LimitQueryEdge (default 1,000,000), Dgraph aborts the query to protect the server. It is a resource-protection limit, not a data error.

Source

Thrown at query/recurse.go:156

		// modify the exec and attach child nodes.
		var out []*SubGraph
		var exp []*SubGraph
		for _, sg := range exec {
			if sg.UnknownAttr {
				continue
			}
			if len(sg.DestUIDs.Uids) == 0 {
				continue
			}
			if exp, err = expandChildren(ctx, sg, startChildren); err != nil {
				return err
			}
			out = append(out, exp...)
		}

		if numEdges > x.Config.LimitQueryEdge {
			// If we've seen too many edges, stop the query.
			return errors.Errorf("Exceeded query edge limit = %v. Found %v edges.",
				x.Config.LimitQueryEdge, numEdges)
		}

		if len(out) == 0 {
			return nil
		}
		exec = out
	}
}

// expandChildren adds child nodes to a SubGraph with no children, expanding them if necessary.
func expandChildren(ctx context.Context, sg *SubGraph, children []*SubGraph) ([]*SubGraph, error) {
	if len(sg.Children) > 0 {
		return nil, errors.New("Subgraph should not have any children")
	}
	// Add children and expand if necessary
	sg.Children = append(sg.Children, children...)
	expandedChildren, err := expandSubgraph(ctx, sg)

View on GitHub (pinned to 759e242be6)

Solutions

  1. Bound the recursion with an explicit depth, e.g. recurse(depth: 3)
  2. Narrow the root set with a filter/root function to reduce starting nodes
  3. Raise the limit in server config (limit{"query-edge": N}) if the server can afford more memory
  4. Restructure the query: use shortest-path or specific predicates instead of full expand-all (_all_directives or expand(_all_))

Example fix

// before: unbounded recurse over everything
{
  me(func: eq(name, "alice")) @recurse {
    expand(_all_)
  }
}
// after: bounded depth and selected predicates
{
  me(func: eq(name, "alice")) @recurse(depth: 3) {
    friend
    name
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Compute expected traversal size before running recurse
maxDepth := 3
if estimateEdgesFromRoot(rootUIDs, maxDepth) > 1_000_000 {
    return errors.New("recurse would exceed query-edge limit; add depth bound or filter")
}

Try / catch

resp, err := txn.Query(ctx, dql)
if err != nil && strings.Contains(err.Error(), "Exceeded query edge limit") {
    // retry with reduced depth or narrowed root set
    dql = reduceDepth(dql)
    resp, err = txn.Query(ctx, dql)
}

Prevention

When it happens

Trigger: A recurse { ... } query whose traversal touches more edges than the limit-query-edge config: starting from high-degree root nodes, deep recursion without a depth bound, or large datasets with dense connectivity.

Common situations: Running recurse from a node with thousands of neighbors, forgetting to set depth: N on huge graphs, defaults changed in self-hosted configs, or per-node limits (query-edge limit) set lower than dataset size.

Related errors


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