d2lang/d2 · error
edge not found
Error message
edge not found
What it means
ReconnectEdge is asked to reconnect the edge addressed by `key`, but the container object that the edge's key path resolves to does not exist in the board's graph. `boardG.Root.HasChild(d2graph.Key(mk.Key))` fails, meaning the prefix of the key before the edge has no matching object. The library refuses to proceed because there is no scope object to look the edge up under.
Source
Thrown at d2oracle/edit.go:161
if len(boardPath) > 0 {
// When compiling a nested board, we can read from boardG but only write to baseBoardG
boardG = GetBoardGraph(g, boardPath)
if boardG == nil {
return nil, fmt.Errorf("board %v not found", boardPath)
}
// TODO beter name
baseAST = boardG.BaseAST
if baseAST == nil {
return nil, fmt.Errorf("board %v cannot be modified through this file", boardPath)
}
}
obj := boardG.Root
if mk.Key != nil {
var ok bool
obj, ok = boardG.Root.HasChild(d2graph.Key(mk.Key))
if !ok {
return nil, errors.New("edge not found")
}
}
edge, ok := obj.HasEdge(mk)
if !ok {
return nil, errors.New("edge not found")
}
if srcKey != nil {
if edge.Src.AbsID() == *srcKey {
srcKey = nil
}
}
if dstKey != nil {
if edge.Dst.AbsID() == *dstKey {
dstKey = nil
}View on GitHub (pinned to 0d69dca6f5)
Solutions
- Verify the object prefix of the key exists in the graph before calling ReconnectEdge (compile the sketch and check HasChild / AbsID).
- Fix typos or quote identifiers containing special characters: use `x."a.b".(c -> d)` style quoting in the key string.
- Confirm you are targeting the right board via boardPath; the edge's container must exist in that nested board.
- Re-fetch the current key from the compiled graph instead of caching keys across edits.
Example fix
// before
g, err := d2oracle.ReconnectEdge(g, []string{"root"}, "contianer.(a -> b)", &newSrc, nil)
// after (typo fixed and existence pre-checked)
key := "container.(a -> b)"
if obj, ok := g.Root.HasChild([]string{"container"}); ok && obj.HasEdge(mk) {
g, err = d2oracle.ReconnectEdge(g, []string{"root"}, key, &newSrc, nil)
} Defensive patterns
Strategy: validation
Validate before calling
mk, err := d2parser.ParseMapKey(key)
if err != nil { return err }
if mk.Key != nil {
if _, ok := g.Root.HasChild(d2graph.Key(mk.Key)); !ok {
return fmt.Errorf("container %v does not exist", key)
}
} Type guard
func edgeContainerExists(g *d2graph.Graph, key string) bool {
mk, err := d2parser.ParseMapKey(key)
if err != nil || mk.Key == nil { return false }
_, ok := g.Root.HasChild(d2graph.Key(mk.Key))
return ok
} Try / catch
g2, err := d2oracle.ReconnectEdge(g, boardPath, key, &src, &dst)
if err != nil {
if err.Error() == "edge not found" {
// re-derive key from current graph and retry once
}
return err
} Prevention
- Always build keys from live graph data (AbsID/edge references), never from cached strings
- Quote identifiers containing dots, spaces, or dashes
- Confirm boardPath matches the board where the edge's container exists
- Re-compile and re-fetch keys after any prior mutation
When it happens
Trigger: Calling d2oracle.ReconnectEdge with a `key` like `x.(a -> b)` where the object path `x` (everything before the edge) does not exist in the graph, e.g. the node was deleted, renamed, or the key is typos/missing quotes for special characters.
Common situations: Editors replaying a stored key after a user renamed a container; keys built for the wrong board (nested boardPath given but edge lives on root); stale client state after a delete; keys whose IDs contain dots/spaces needing quoting (`"a.b"`) but passed raw.
Related errors
- newSrc not found
- newDst not found
- edgeKey must be an edge
- edgeKey must refer to an existing edge
- can only set one edge at a time
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/c966f3010430d39f.
Report an issue: GitHub.