{"record":{"id":"20548c1cc91df526","repo":"dgraph-io/dgraph","slug":"invalid-recurse-path-query","errorCode":null,"errorMessage":"Invalid recurse path query","messagePattern":"Invalid recurse path query","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"query/recurse.go","lineNumber":194,"sourceCode":"\t\treturn nil, err\n\t}\n\tout := make([]*SubGraph, 0, len(expandedChildren))\n\tsg.Children = sg.Children[:0]\n\t// Link new child nodes back to parent destination UIDs\n\tfor _, child := range expandedChildren {\n\t\tnewChild := new(SubGraph)\n\t\tnewChild.copyFiltersRecurse(child)\n\t\tnewChild.SrcUIDs = sg.DestUIDs\n\t\tnewChild.Params.Var = child.Params.Var\n\t\tsg.Children = append(sg.Children, newChild)\n\t\tout = append(out, newChild)\n\t}\n\treturn out, nil\n}\n\nfunc recurse(ctx context.Context, sg *SubGraph) error {\n\tif !sg.Params.Recurse {\n\t\treturn errors.Errorf(\"Invalid recurse path query\")\n\t}\n\n\tdepth := sg.Params.RecurseArgs.Depth\n\tif depth == 0 {\n\t\tif sg.Params.RecurseArgs.AllowLoop {\n\t\t\treturn errors.Errorf(\"Depth must be > 0 when loop is true for recurse query\")\n\t\t}\n\t\t// If no depth is specified, expand till we reach all leaf nodes\n\t\t// or we see reach too many nodes.\n\t\tdepth = math.MaxUint64\n\t}\n\n\tfor _, child := range sg.Children {\n\t\tif len(child.Children) > 0 {\n\t\t\treturn errors.Errorf(\n\t\t\t\t\"recurse queries require that all predicates are specified in one level\")\n\t\t}\n\t}","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/query/recurse.go#L176-L212","documentation":"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.","triggerScenarios":"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).","commonSituations":"Typos in the recurse directive syntax, nesting @recurse inside sub-blocks, or copy-pasted queries mixing recurse with shortest/shortestpath features.","solutions":["Ensure the @recurse directive is syntactically valid at the root block: @recurse(depth: N) or @recurse","Do not nest @recurse inside child blocks; it applies at the top level of the query block","Remove recurse from queries that also use shortest path — combine them differently","Test a minimal recurse query first, then add filters/directives back"],"exampleFix":"// before: nested recurse\n{\n  me(func: eq(name, \"a\")) {\n    friend @recurse { uid }\n  }\n}\n// after: recurse at root\n{\n  me(func: eq(name, \"a\")) @recurse {\n    friend\n    uid\n  }\n}","handlingStrategy":"validation","validationCode":"// Validate the query uses @recurse at the top-level block before sending\nif !strings.Contains(dql, \"@recurse\") {\n    return errors.New(\"recurse processing requires @recurse directive at root block\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := txn.Query(ctx, dql)\nif err != nil && strings.Contains(err.Error(), \"Invalid recurse path query\") {\n    return fmt.Errorf(\"malformed recurse query: %w\", err) // fix DQL, don't retry\n}","preventionTips":["Place @recurse only on the top-level query block","Never nest @recurse inside child edge blocks","Validate DQL in Ratel before deploying"],"tags":["recurse","query-syntax","dgraph"],"backgroundTag":"invalid-recurse-query","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}