{"record":{"id":"3c0af3c1c17d799a","repo":"dgraph-io/dgraph","slug":"recurse-queries-require-that-all-predicates-are-sp","errorCode":null,"errorMessage":"recurse queries require that all predicates are specified in one level","messagePattern":"recurse queries require that all predicates are specified in one level","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"query/recurse.go","lineNumber":209,"sourceCode":"\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}\n\n\treturn sg.expandRecurse(ctx, depth)\n}\n","sourceCodeStart":191,"sourceCodeEnd":216,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/query/recurse.go#L191-L216","documentation":"Recurse queries only support one level of predicates: every child of the recurse root must be a leaf. If any child block itself has nested children, Dgraph rejects the query because nested expansion under recursion is not supported.","triggerScenarios":"Writing a @recurse query where a child edge block contains its own nested block, e.g. @recurse { friend { name { x } } }, or adding @filter/directives blocks that create child SubGraphs with children.","commonSituations":"Copy-pasting a nested normal query and adding @recurse on top; assuming recursion supports arbitrary nesting like regular queries do.","solutions":["Flatten the query: list all desired predicates as direct children of the recurse block","Move any nested selection fields up one level, dropping deeper nesting","If nested traversal shape is required, use multiple queries or shortest-path/normal queries instead of recurse"],"exampleFix":"// before: nested children under recurse\n{\n  me(func: eq(name, \"a\")) @recurse {\n    friend {\n      name\n      know {\n        age\n      }\n    }\n  }\n}\n// after: one level only\n{\n  me(func: eq(name, \"a\")) @recurse {\n    friend\n    name\n  }\n}","handlingStrategy":"validation","validationCode":"// Reject nested blocks under recurse before sending\ninRecurse := false\nbracketDepth := 0\nfor _, line := range strings.Split(dql, \"\\n\") {\n    if strings.Contains(line, \"@recurse\") { inRecurse = true; continue }\n    bracketDepth += strings.Count(line, \"{\") - strings.Count(line, \"}\")\n    if inRecurse && bracketDepth > 1 {\n        return errors.New(\"recurse supports only one level of predicates\")\n    }\n}","typeGuard":null,"tryCatchPattern":"resp, err := txn.Query(ctx, dql)\nif err != nil && strings.Contains(err.Error(), \"one level\") {\n    return fmt.Errorf(\"flatten recurse query: %w\", err) // fix DQL, don't retry\n}","preventionTips":["Keep recurse children as flat predicate lists","Move nested selections into separate queries","Lint generated DQL for nesting depth under @recurse blocks"],"tags":["recurse","query-syntax","validation","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"}