d2lang/d2 · error
to parent not found
Error message
to parent not found
What it means
During a move/rename, MoveIDDeltas computes the parent of the destination ID from the parsed new key ak2. If the destination has multiple path segments, it looks up the ancestors under the root with HasChild; when those intermediate containers do not exist in the graph, the move cannot proceed and it returns 'to parent not found'.
Source
Thrown at d2oracle/edit.go:2908
return nil, nil
}
beforeID := e.AbsID()
tmp := *e
e2 := &tmp
e2.SrcArrow = mk2.Edges[0].SrcArrow == "<"
e2.DstArrow = mk2.Edges[0].DstArrow == ">"
deltas[beforeID] = e2.AbsID()
return deltas, nil
}
beforeObjID := obj.ID
toParent := g.Root
if len(ak2) > 1 {
var ok bool
toParent, ok = g.Root.HasChild(ak2[:len(ak2)-1])
if !ok {
return nil, errors.New("to parent not found")
}
}
id := ak2[len(ak2)-1]
tmpRenames := func() func() {
if isCrossScope && !includeDescendants {
for _, ch := range obj.ChildrenArray {
ch.Parent = obj.Parent
}
}
prevParent := obj.Parent
obj.Parent = toParent
obj.ID = id
for k, v := range conflictNewIDs {
k.ID = v
}View on GitHub (pinned to 0d69dca6f5)
Solutions
- Create the destination parent containers first (e.g. via oracle.Set for the full path) before moving the object
- Use d2graph g.Root.HasChild(parentPath) in the caller to verify the parent exists before calling MoveIDDeltas
- Check for typos or board-scope mistakes in the destination ID path
Example fix
// before
renamed, err := oracle.MoveIDDeltas(ctx, g, "x", "a.b.x", nil) // 'a.b' may not exist
// after
if _, ok := g.Root.HasChild([]string{"a", "b"}); ok {
renamed, err = oracle.MoveIDDeltas(ctx, g, "x", "a.b.x", nil)
} else {
// create containers a and b first
} Defensive patterns
Strategy: validation
Validate before calling
if len(ak2) > 1 {
if _, ok := g.Root.HasChild(ak2[:len(ak2)-1]); !ok {
return errors.New("destination parent does not exist")
}
} Type guard
func parentExists(g *d2graph.Graph, path []string) bool {
if len(path) <= 1 { return true }
_, ok := g.Root.HasChild(path[:len(path)-1])
return ok
} Try / catch
_, err := oracle.MoveIDDeltas(ctx, g, oldID, newName, nil)
if err != nil && strings.Contains(err.Error(), "to parent not found") {
// create parent containers, then retry once
} Prevention
- Always verify destination parent path exists with HasChild before moving
- Create namespaces with oracle.Set before moving objects into them
- Watch for board-scope paths differing from root scope
When it happens
Trigger: Calling MoveIDDeltas with a newName whose parent path (ak2[:len(ak2)-1], when len(ak2)>1) does not resolve to an existing container in the graph, e.g. moving 'x' to 'a.b.c' where 'a.b' does not exist.
Common situations: Renaming an object into a namespace that was renamed or deleted elsewhere; typos in the destination path; moving objects between boards where the target scope was never created; stale references in tooling built on the oracle API.
Related errors
- expected "shadow" to be true or false
- expected "3d" to be true or false
- expected "multiple" to be true or false
- expected "font-size" to be a number between 8 and 100
- expected "font-color" to be a valid named color ("orange"),
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/20520bf6cf3cb8d7.
Report an issue: GitHub.