dgraph-io/dgraph · error

Invalid recurse path query

Error message

Invalid recurse path query

What it means

The recurse() function rejects any SubGraph that does not have Params.Recurse set. This error means the recurse entry point was reached for a query not actually marked as a recurse query — an internal invariant / malformed query shape. It essentially guards the recurse processing path.

Source

Thrown at query/recurse.go:194

		return nil, err
	}
	out := make([]*SubGraph, 0, len(expandedChildren))
	sg.Children = sg.Children[:0]
	// Link new child nodes back to parent destination UIDs
	for _, child := range expandedChildren {
		newChild := new(SubGraph)
		newChild.copyFiltersRecurse(child)
		newChild.SrcUIDs = sg.DestUIDs
		newChild.Params.Var = child.Params.Var
		sg.Children = append(sg.Children, newChild)
		out = append(out, newChild)
	}
	return out, nil
}

func recurse(ctx context.Context, sg *SubGraph) error {
	if !sg.Params.Recurse {
		return errors.Errorf("Invalid recurse path query")
	}

	depth := sg.Params.RecurseArgs.Depth
	if depth == 0 {
		if sg.Params.RecurseArgs.AllowLoop {
			return errors.Errorf("Depth must be > 0 when loop is true for recurse query")
		}
		// If no depth is specified, expand till we reach all leaf nodes
		// or we see reach too many nodes.
		depth = math.MaxUint64
	}

	for _, child := range sg.Children {
		if len(child.Children) > 0 {
			return errors.Errorf(
				"recurse queries require that all predicates are specified in one level")
		}
	}

View on GitHub (pinned to 759e242be6)

Solutions

  1. Ensure the @recurse directive is syntactically valid at the root block: @recurse(depth: N) or @recurse
  2. Do not nest @recurse inside child blocks; it applies at the top level of the query block
  3. Remove recurse from queries that also use shortest path — combine them differently
  4. Test a minimal recurse query first, then add filters/directives back

Example fix

// before: nested recurse
{
  me(func: eq(name, "a")) {
    friend @recurse { uid }
  }
}
// after: recurse at root
{
  me(func: eq(name, "a")) @recurse {
    friend
    uid
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the query uses @recurse at the top-level block before sending
if !strings.Contains(dql, "@recurse") {
    return errors.New("recurse processing requires @recurse directive at root block")
}

Try / catch

resp, err := txn.Query(ctx, dql)
if err != nil && strings.Contains(err.Error(), "Invalid recurse path query") {
    return fmt.Errorf("malformed recurse query: %w", err) // fix DQL, don't retry
}

Prevention

When it happens

Trigger: Sending a query whose structure routes into recurse processing without the @recurse directive properly parsed, e.g. malformed recurse syntax, nesting recurse inside another recurse, or using recurse where unsupported (e.g. in shortest path blocks).

Common situations: Typos in the recurse directive syntax, nesting @recurse inside sub-blocks, or copy-pasted queries mixing recurse with shortest/shortestpath features.

Related errors


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