d2lang/d2 · error
newSrc not found
Error message
newSrc not found
What it means
ReconnectEdge resolved the new source endpoint via `boardG.Root.HasChild`, but no object exists for the `srcKey` you passed. The edge's existing endpoints are found; the replacement source is not. Unlike the edge's other endpoints, ReconnectEdge does not create missing nodes for the new endpoint lookup.
Source
Thrown at d2oracle/edit.go:195
if edge.Dst.AbsID() == *dstKey {
dstKey = nil
}
}
if srcKey == nil && dstKey == nil {
return g, nil
}
var src *d2graph.Object
var dst *d2graph.Object
if srcKey != nil {
srcmk, err := d2parser.ParseMapKey(*srcKey)
if err != nil {
return nil, err
}
src, ok = boardG.Root.HasChild(d2graph.Key(srcmk.Key))
if !ok {
return nil, errors.New("newSrc not found")
}
}
if dstKey != nil {
dstmk, err := d2parser.ParseMapKey(*dstKey)
if err != nil {
return nil, err
}
dst, ok = boardG.Root.HasChild(d2graph.Key(dstmk.Key))
if !ok {
return nil, errors.New("newDst not found")
}
}
refs := edge.References
if baseAST != g.AST {
refs = GetWriteableEdgeRefs(edge, baseAST)
if len(refs) == 0 || refs[0].ScopeAST != baseAST {
// TODO nullView on GitHub (pinned to 0d69dca6f5)
Solutions
- Create the new source node first (e.g. via d2oracle.Create) so it exists in the graph before reconnecting.
- Verify srcKey resolves: parse it and check g.Root.HasChild(d2graph.Key(...)) before calling.
- Use the node's AbsID() as srcKey to guarantee exact matching.
- Ensure srcKey refers to a node in the same board passed via boardPath.
Example fix
// before
g, err = d2oracle.ReconnectEdge(g, nil, "x.(a -> b)", &newSrc, nil) // newSrc="q" doesn't exist
// after: ensure node exists first
if _, ok := g.Root.HasChild([]string{"q"}); !ok {
g, _, err = d2oracle.Create(g, nil, "q", nil)
}
g, err = d2oracle.ReconnectEdge(g, nil, "x.(a -> b)", &newSrc, nil) Defensive patterns
Strategy: validation
Validate before calling
srcmk, err := d2parser.ParseMapKey(newSrc)
if err != nil { return err }
if _, ok := g.Root.HasChild(d2graph.Key(srcmk.Key)); !ok {
g, _, err = d2oracle.Create(g, nil, newSrc, nil)
if err != nil { return err }
} Type guard
func nodeExists(g *d2graph.Graph, id string) bool {
mk, err := d2parser.ParseMapKey(id)
if err != nil { return false }
_, ok := g.Root.HasChild(d2graph.Key(mk.Key))
return ok
} Try / catch
g2, err := d2oracle.ReconnectEdge(g, nil, key, &newSrc, &newDst)
if err != nil && err.Error() == "newSrc not found" {
g, _, err = d2oracle.Create(g, nil, newSrc, nil)
if err != nil { return err }
g2, err = d2oracle.ReconnectEdge(g, nil, key, &newSrc, &newDst)
} Prevention
- Create endpoint nodes before reconnecting edges to them
- Pass node AbsID() values as srcKey/dstKey
- Keep node existence checks next to every rewire operation
- Watch for nodes created inside nested boards that are invisible to the target board
When it happens
Trigger: Calling d2oracle.ReconnectEdge with `srcKey` pointing to a node that does not exist in the target board: typo, node deleted earlier, node lives in a different board than boardPath, or an absolute ID that doesn't match the graph (e.g. wrong quotes/escapes).
Common situations: Batch scripts reconnecting edges after bulk node deletion; renaming a node then reconnecting with the old name; passing IDs from a different nested board; special characters in IDs not quoted.
Related errors
- newDst not found
- edge 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/106531e84b5a0300.
Report an issue: GitHub.