{"record":{"id":"ef62f21206e63dfc","repo":"d2lang/d2","slug":"invalid-use-of-parent","errorCode":null,"errorMessage":"invalid use of parent \"_\"","messagePattern":"invalid use of parent \"_\"","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2graph/d2graph.go","lineNumber":810,"sourceCode":"\t\t\t}\n\t\t}\n\t}\n\n\tresolvedObj = obj\n\tresolvedIDA = ida\n\n\tfor i, id := range ida {\n\t\tif id != \"_\" {\n\t\t\tcontinue\n\t\t}\n\t\tif i != 0 && ida[i-1] != \"_\" {\n\t\t\treturn nil, nil, errors.New(`parent \"_\" can only be used in the beginning of paths, e.g. \"_.x\"`)\n\t\t}\n\t\tif resolvedObj == obj.Graph.Root {\n\t\t\treturn nil, nil, errors.New(`parent \"_\" cannot be used in the root scope`)\n\t\t}\n\t\tif i == len(ida)-1 {\n\t\t\treturn nil, nil, errors.New(`invalid use of parent \"_\"`)\n\t\t}\n\t\tresolvedObj = resolvedObj.Parent\n\t\tresolvedIDA = resolvedIDA[1:]\n\t}\n\n\treturn resolvedObj, resolvedIDA, nil\n}\n\n// TODO: remove edges []edge and scope each edge inside Object.\nfunc (obj *Object) FindEdges(mk *d2ast.Key) ([]*Edge, bool) {\n\tif len(mk.Edges) != 1 {\n\t\treturn nil, false\n\t}\n\tif mk.EdgeIndex.Int == nil {\n\t\treturn nil, false\n\t}\n\tae := mk.Edges[0]\n","sourceCodeStart":792,"sourceCodeEnd":828,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2graph/d2graph.go#L792-L828","documentation":"A `_` (parent) token in a path is valid only when followed by at least one more identifier, e.g. `_.x`. A path that ends with `_` (nothing to resolve after going up a level) is meaningless, so resolution fails with this error.","triggerScenarios":"Resolving a path whose last segment is `_`, such as `a._` or `_.`, via map key parsing or d2graph path resolution.","commonSituations":"Trailing underscore typos like `container._` when intending `container._.child`; generated paths where a final segment was dropped.","solutions":["Add the target identifier after the `_`: write `_.child` instead of `_`.","If you intended to reference the container itself, just use its name directly.","Double-check generated/templated paths so no segment is dropped leaving a trailing `_`."],"exampleFix":"// before\na._\n// after\na._.child","handlingStrategy":"validation","validationCode":"func pathNotEndingInParent(path string) bool {\n  segs := strings.Split(path, \".\")\n  return segs[len(segs)-1] != \"_\"\n}","typeGuard":"func lastSegmentIsTarget(ida []string) bool { return len(ida) > 0 && ida[len(ida)-1] != \"_\" }","tryCatchPattern":"if _, _, err := g.MiddlePath(obj, ida); err != nil && strings.Contains(err.Error(), `invalid use of parent`) {\n  // append a missing target segment or strip the trailing _ before retrying\n}","preventionTips":["Never end a path with `_`.","Validate generated paths segment-by-segment.","Trim trailing `.`/`_` artifacts from string-built paths."],"tags":["d2","path-resolution","syntax"],"backgroundTag":"invalid-parent-reference","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}