d2lang/d2 · error
parent "_" cannot be used in the root scope
Error message
parent "_" cannot be used in the root scope
What it means
`_` resolves to the parent of the current scope. When the current scope is already the root object, there is no parent, so d2graph rejects the reference with this error during path resolution.
Source
Thrown at d2graph/d2graph.go:807
}
if referencesActor {
obj = objSD
}
}
}
resolvedObj = obj
resolvedIDA = ida
for i, id := range ida {
if id != "_" {
continue
}
if i != 0 && ida[i-1] != "_" {
return nil, nil, errors.New(`parent "_" can only be used in the beginning of paths, e.g. "_.x"`)
}
if resolvedObj == obj.Graph.Root {
return nil, nil, errors.New(`parent "_" cannot be used in the root scope`)
}
if i == len(ida)-1 {
return nil, nil, errors.New(`invalid use of parent "_"`)
}
resolvedObj = resolvedObj.Parent
resolvedIDA = resolvedIDA[1:]
}
return resolvedObj, resolvedIDA, nil
}
// TODO: remove edges []edge and scope each edge inside Object.
func (obj *Object) FindEdges(mk *d2ast.Key) ([]*Edge, bool) {
if len(mk.Edges) != 1 {
return nil, false
}
if mk.EdgeIndex.Int == nil {
return nil, falseView on GitHub (pinned to 0d69dca6f5)
Solutions
- Remove the `_` prefix and reference `x` directly, since at root scope the name is already unambiguous.
- If the reference must be relative, move it inside the nested scope where `_` has a parent to climb.
- Use the absolute path from root instead of a parent-relative path.
Example fix
// before (at root scope) _.x // after x
Defensive patterns
Strategy: validation
Validate before calling
func underscoreAllowedAtRoot(path string) bool { return !strings.HasPrefix(path, "_.") } // at root scope, don't use _. prefix Type guard
func isRootScope(obj *d2graph.Object) bool { return obj.Parent == nil } Try / catch
if _, _, err := g.MiddlePath(obj, ida); err != nil && strings.Contains(err.Error(), "root scope") {
ida = ida[1:] // drop the leading _ and retry
} Prevention
- At root scope, reference names directly without `_`.
- When templating relative references, check current nesting depth first.
- Prefer absolute paths in generated code.
When it happens
Trigger: Using `_.x` (or `_.x.y`) at the top level of a d2 file / root scope, where the resolved parent of root does not exist — e.g. a top-level map key like `_.x` or a d2oracle call at root scope.
Common situations: Copy-pasting a relative reference from inside a nested block to the top level; macros or templates that emit `_.` prefixes regardless of nesting depth.
Related errors
- parent "_" can only be used in the beginning of paths, e.g.
- invalid use of parent "_"
- expected "shadow" to be true or false
- expected "3d" to be true or false
- expected "multiple" to be true or false
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/c2d08be336858d20.
Report an issue: GitHub.