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

  1. Verify the object exists (e.g. via d2graph or GetBoardGraph + Root.HasChild) before deleting.
  2. Correct the key path spelling and nesting in the key string.
  3. If the object may already be absent, treat this error as a no-op in your wrapper or check existence first.
  4. 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

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


AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31). Data as JSON: /api/errors/3be12635879e6dd5. Report an issue: GitHub.