d2lang/d2 · error
parent "_" can only be used in the beginning of paths, e.g.
Error message
parent "_" can only be used in the beginning of paths, e.g. "_.x"
What it means
In d2 path resolution, the `_` token means 'parent'. It is only meaningful as a leading token chain at the start of a path (e.g. `_.x`, `_._.x`). A `_` appearing after a normal identifier is ambiguous, so resolution fails with this error.
Source
Thrown at d2graph/d2graph.go:804
referencesActor = true
break
}
}
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, falseView on GitHub (pinned to 0d69dca6f5)
Solutions
- Move all `_` tokens to the beginning of the path: use `_.a.b` instead of `a._.b`.
- If you meant the object literally named with an underscore path, restructure so the reference is relative from the current scope, e.g. write `_.a` at the right nesting level.
- If the target is absolute, use a full path from root instead of mixing `_` mid-path.
- Quote the identifier if you actually meant a literal `_` character as part of a name.
Example fix
// before a._.b // after _.a.b
Defensive patterns
Strategy: validation
Validate before calling
func validParentPath(path string) bool {
segs := strings.Split(path, ".")
for i, s := range segs {
if s == "_" && i != 0 && segs[i-1] != "_" { return false }
}
return true
} Type guard
func hasValidUnderscoreUse(ida []string) bool {
for i, id := range ida {
if id == "_" && i != 0 && ida[i-1] != "_" { return false }
}
return true
} Try / catch
obj, ida, err := g.MiddlePath(obj, ida)
if err != nil && strings.Contains(err.Error(), `parent "_"`) {
// rewrite the path with _ tokens at the front and retry
} Prevention
- Only use `_` as a leading path prefix.
- Never interleave `_` between normal identifiers.
- Quote identifiers if you mean a literal underscore-named segment.
When it happens
Trigger: Resolving/compiling a path such as `a._.b` or `x.y._` where `_` appears at index > 0 and the previous token is not `_` — e.g. referencing `a._.b` inside a map key or via d2oracle paths.
Common situations: Writing relative references like `parent.child._.other` assuming `_` works anywhere in the path; tools generating paths programmatically appending `_` mid-path; misunderstanding that `_` is only a prefix operator.
Related errors
- invalid use of parent "_"
- parent "_" cannot be used in the root scope
- failed to parse value %q: %w
- expected "shadow" to be true or false
- expected "3d" to be true or false
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/4503c9635dc31ba7.
Report an issue: GitHub.