d2lang/d2 · error
edgeKey must refer to an existing edge
Error message
edgeKey must refer to an existing edge
What it means
ReconnectEdge requires the edgeKey to include an explicit edge index (e.g. `(a -> b)[0]`) so it knows which edge to modify when multiple edges exist on the key. If mk.EdgeIndex is nil after parsing, the key doesn't disambiguate an existing edge and this error is thrown.
Source
Thrown at d2oracle/edit.go:135
return nil, fmt.Errorf("board %v AST not found", boardPath)
}
}
return recompile(g)
}
func ReconnectEdge(g *d2graph.Graph, boardPath []string, edgeKey string, srcKey, dstKey *string) (_ *d2graph.Graph, err error) {
mk, err := d2parser.ParseMapKey(edgeKey)
if err != nil {
return nil, err
}
if len(mk.Edges) == 0 {
return nil, errors.New("edgeKey must be an edge")
}
if mk.EdgeIndex == nil {
return nil, errors.New("edgeKey must refer to an existing edge")
}
edgeTrimCommon(mk)
boardG := g
baseAST := g.AST
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)
}View on GitHub (pinned to 0d69dca6f5)
Solutions
- Use the indexed key form: "(a -> b)[0]" instead of "a -> b".
- Take the exact key from g.Edges[i].AST / the board AST rather than constructing it manually.
- If multiple edges share the key, identify the correct index and pass it via edgeIndex while the key includes the (…)[] form.
- Use d2oracle to inspect g.Edges and reuse its key string verbatim.
Example fix
// before ReconnectEdge(g, "a -> b", 0, "c", "d") // after ReconnectEdge(g, "(a -> b)[0]", 0, "c", "d")
Defensive patterns
Strategy: validation
Validate before calling
mk, _ := d2parser.ParseMapKey(edgeKey)
if mk != nil && mk.EdgeIndex == nil {
edgeKey = fmt.Sprintf("(%s)[0]", edgeKey)
} Type guard
func edgeKeyHasIndex(edgeKey string) bool {
mk, err := d2parser.ParseMapKey(edgeKey)
return err == nil && mk != nil && mk.EdgeIndex != nil
} Try / catch
newKey, err := d2oracle.ReconnectEdge(g, edgeKey, edgeIndex, newSrc, newDst)
if err != nil && err.Error() == "edgeKey must refer to an existing edge" {
// add the (key)[index] form and retry
} Prevention
- Use the (key)[index] form for edge keys passed to d2oracle edits.
- Copy keys verbatim from the graph AST instead of reconstructing them.
- Include the edge index whenever multiple edges may share a key.
When it happens
Trigger: Calling ReconnectEdge with an edge key like "a -> b" that omits the (key)[index] form, or with an index/key combination that parsed to nil EdgeIndex — commonly when the key has multiple edge representations.
Common situations: Using g.Edges[i].Key straight from the graph when it lacks an index for multi-edge keys; hand-writing edge keys in tools and omitting the [0] index; multiple connections between the same endpoints requiring index disambiguation.
Related errors
- edgeKey must be an edge
- edge not found
- newSrc not found
- newDst not found
- can only set one edge at a time
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/4c92c5335d483b08.
Report an issue: GitHub.