d2lang/d2 · error
object not found
Error message
object not found
What it means
During Delete's reserved-key handling, the code walks down the key path from the root object with HasChild for each id segment; if any segment has no matching child, it fails with "object not found". This means the key you asked to delete does not resolve to an existing object in the (board's) graph.
Source
Thrown at d2oracle/edit.go:1411
id == "height" ||
id == "left" ||
id == "top" ||
id == "link" {
deleted, err := deleteObjField(g, baseAST, obj, id)
if err != nil {
return nil, err
}
if !deleted && imported {
mk.Value = d2ast.MakeValueBox(&d2ast.Null{})
appendMapKey(baseAST, mk)
} else {
}
}
break
}
obj, ok = obj.HasChild([]string{id})
if !ok {
return nil, fmt.Errorf("object not found")
}
imported = IsImportedObj(baseAST, obj)
}
return recompile(g)
}
func deleteMapField(m *d2ast.Map, field string) (deleted bool) {
for i := 0; i < len(m.Nodes); i++ {
n := m.Nodes[i]
if n.MapKey != nil && n.MapKey.Key != nil {
if n.MapKey.Key.Path[0].Unbox().ScalarString() == field {
deleteFromMap(m, n.MapKey)
} else if n.MapKey.Key.Path[0].Unbox().ScalarString() == "style" ||
n.MapKey.Key.Path[0].Unbox().ScalarString() == "label" ||
n.MapKey.Key.Path[0].Unbox().ScalarString() == "icon" ||
n.MapKey.Key.Path[0].Unbox().ScalarString() == "source-arrowhead" ||
n.MapKey.Key.Path[0].Unbox().ScalarString() == "target-arrowhead" {View on GitHub (pinned to 0d69dca6f5)
Solutions
- Verify the object exists (e.g. via d2graph or GetBoardGraph + Root.HasChild) before deleting.
- Correct the key path spelling and nesting in the key string.
- If the object may already be absent, treat this error as a no-op in your wrapper or check existence first.
- Confirm you are targeting the correct boardPath where the object is defined.
Example fix
// before
g, err := d2oracle.Delete(g, nil, "x.y.z") // z doesn't exist
// after
if _, ok := g.Root.HasChild([]string{"x","y","z"}); ok {
g, err = d2oracle.Delete(g, nil, "x.y.z")
} Defensive patterns
Strategy: validation
Validate before calling
import "oss.terrastruct.com/d2/d2graph"
if _, ok := g.Root.HasChild(d2graph.Key(mk)); !ok {
return nil // nothing to delete; skip the call
} Type guard
func objectExists(g *d2graph.Graph, ids []string) bool {
_, ok := g.Root.HasChild(ids)
return ok
} Try / catch
g2, err := d2oracle.Delete(g, boardPath, key)
if err != nil && strings.Contains(err.Error(), "object not found") {
return g, nil // treat as idempotent no-op
} Prevention
- Check existence before deleting; deletes are not idempotent here.
- Keep key strings in sync with actual object paths.
- Recompile after prior structural edits.
- Don't address glob-created children by literal path.
When it happens
Trigger: deleteReserved — called by Delete with a key whose path contains a segment that doesn't exist as a child object (typo, deleted already, or path too deep), particularly for keys touching reserved contexts.
Common situations: Deleting an object twice (second call should be a no-op but this path errors); key strings referencing objects defined only on a different board; glob-generated children addressed by literal name.
Related errors
- can only delete one edge at a time
- 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
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/3be12635879e6dd5.
Report an issue: GitHub.