{"record":{"id":"b6026bc2dc9aa26d","repo":"dgraph-io/dgraph","slug":"expand-not-allowed-inside-shortest","errorCode":null,"errorMessage":"expand() not allowed inside shortest","messagePattern":"expand\\(\\) not allowed inside shortest","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"query/query.go","lineNumber":538,"sourceCode":"\t\t// empty because MathExp should have atleast one of them.\n\t\tkey = fmt.Sprintf(\"val(%+v)\", gchild.Var)\n\t}\n\tif gchild.IsGroupby {\n\t\tkey += \"groupby\"\n\t}\n\treturn key\n}\n\nfunc treeCopy(gq *dql.GraphQuery, sg *SubGraph) error {\n\t// Typically you act on the current node, and leave recursion to deal with\n\t// children. But, in this case, we don't want to muck with the current\n\t// node, because of the way we're dealing with the root node.\n\t// So, we work on the children, and then recurse for grand children.\n\tattrsSeen := make(map[string]struct{})\n\n\tfor _, gchild := range gq.Children {\n\t\tif sg.Params.Alias == \"shortest\" && gchild.Expand != \"\" {\n\t\t\treturn errors.Errorf(\"expand() not allowed inside shortest\")\n\t\t}\n\n\t\tkey := \"\"\n\t\tif gchild.Alias != \"\" {\n\t\t\tkey = gchild.Alias\n\t\t} else {\n\t\t\tkey = uniqueKey(gchild)\n\t\t}\n\t\tif _, ok := attrsSeen[key]; ok {\n\t\t\treturn errors.Errorf(\"%s not allowed multiple times in same sub-query.\",\n\t\t\t\tkey)\n\t\t}\n\t\tattrsSeen[key] = struct{}{}\n\n\t\targs := params{\n\t\t\tAlias:        gchild.Alias,\n\t\t\tExpand:       gchild.Expand,\n\t\t\tFacet:        gchild.Facets,","sourceCodeStart":520,"sourceCodeEnd":556,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/query/query.go#L520-L556","documentation":"Dgraph rejects a query that uses expand(...), the recursive edge-expansion function, inside a shortest-path block. expand() is only meaningful for regular subgraph traversal; combined with shortest() it would make the path search undefined or unbounded, so treeCopy fails fast during query parsing. The check runs for any direct child of the query whose Params.Alias is \"shortest\".","triggerScenarios":"Sending a GraphQL+- query with a shortest path block containing an expand(_) child, e.g. `shortest(from: uid, to: uid) { expand(_all_) }`. Produced in treeCopy when Params.Alias == \"shortest\" and gchild.Expand is non-empty.","commonSituations":"Developers migrating traversal queries to shortest-path queries copy an expand() line into the shortest block; tutorials mixing path-finding with generic schema exploration; dynamic query builders that append expand to every level.","solutions":["Remove the expand() child from inside the shortest path block","List the specific predicates you want the path to traverse as children instead of expand","If you need generic traversal plus shortest path, run two separate queries and combine results client-side"],"exampleFix":"// before\nquery {\n  shortest(from: 0x1, to: 0x2) {\n    expand(_all_)\n  }\n}\n// after\nquery {\n  shortest(from: 0x1, to: 0x2) {\n    friend\n    knows\n  }\n}","handlingStrategy":"validation","validationCode":"const shortestBlocks = [...parsedQuery.matchAll(/shortest\\s*\\(([^)]*)\\)\\s*\\{([^}]*)\\}/g)];\nfor (const [, , body] of shortestBlocks) {\n  if (/expand\\s*\\(/.test(body)) throw new Error('expand() is not allowed inside shortest; list predicates explicitly');\n}","typeGuard":"function isShortestWithExpand(child) { return child.alias === 'shortest' && typeof child.expand === 'string' && child.expand.length > 0; }","tryCatchPattern":"try {\n  const res = await dgraph.newTxn().query(q);\n} catch (e) {\n  if (e.message.includes('expand() not allowed inside shortest')) {\n    throw new Error('Query rewrite needed: remove expand() from shortest block');\n  }\n  throw e;\n}","preventionTips":["Never place expand() inside shortest blocks; expand is for generic traversal only","List the exact predicates you want the path to consider","Lint queries with a rule flagging expand within shortest"],"tags":["dgraph","query","graphql-plus","validation"],"backgroundTag":"invalid-query-argument","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}