d2lang/d2 · error
board %v cannot be modified through this file
Error message
board %v cannot be modified through this file
What it means
d2oracle.Create edits a board by locating its graph via GetBoardGraph(g, boardPath) and using the board's BaseAST (the original AST slice in the parent file) as the write target. When BaseAST is nil the board exists in the compiled graph but has no original AST node in the file (e.g. it was generated programmatically or is a root/imported board), so Create refuses to write edits 'through this file' and returns this error.
Source
Thrown at d2oracle/edit.go:46
return "operation would modify AST outside of given scope"
}
func Create(g *d2graph.Graph, boardPath []string, key string) (_ *d2graph.Graph, newKey string, err error) {
defer xdefer.Errorf(&err, "failed to create %#v", key)
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)
}
}
newKey, edge, err := generateUniqueKey(boardG, key, nil, nil)
if err != nil {
return nil, "", err
}
if edge {
err = _set(boardG, baseAST, key, nil, nil)
} else {
err = _set(boardG, baseAST, newKey, nil, nil)
}
if len(boardPath) > 0 {
replaced := ReplaceBoardNode(g.AST, baseAST, boardPath)
if !replaced {
return nil, "", fmt.Errorf("board %v AST not found", boardPath)View on GitHub (pinned to 0d69dca6f5)
Solutions
- Ensure the target board is declared in the file whose AST g was compiled from (e.g. under layers:, scenarios:, or steps:) so its BaseAST is populated.
- Apply the edit to the graph that owns the board's file instead of routing it through g with a boardPath.
- Pass an empty boardPath and edit the root board if that is what you actually intend.
- Recompile the whole diagram from source after mutating the in-memory board, rather than using d2oracle for that board.
Example fix
// before
g2, _, err := d2oracle.Create(g, []string{"layers", "generated"}, "x") // BaseAST nil -> error
// after
boardG := d2oracle.GetBoardGraph(g, []string{"layers", "generated"})
if boardG.BaseAST == nil {
// edit the owning graph's AST or recompile from serialized source instead
g2, _, err = d2oracle.Create(g, nil, "x")
} Defensive patterns
Strategy: validation
Validate before calling
func canEditBoard(g *d2graph.Graph, boardPath []string) bool {
if len(boardPath) == 0 { return true }
bg := d2oracle.GetBoardGraph(g, boardPath)
return bg != nil && bg.BaseAST != nil
} Type guard
func editableBoard(bg *d2graph.Graph) bool { return bg != nil && bg.BaseAST != nil } Try / catch
g2, _, err := d2oracle.Create(g, boardPath, key)
if err != nil && strings.Contains(err.Error(), "cannot be modified through this file") {
// fall back to editing the owning graph or recompiling from source
} Prevention
- Only target boards declared in the file backing g.AST
- Check GetBoardGraph(...).BaseAST != nil before oracle calls
- Edit the root board when boardPath is unnecessary
When it happens
Trigger: Calling Create(g, boardPath, key) where boardPath resolves to a board whose graph has a nil BaseAST — typically a board created only in-memory, a board defined in a file other than the one backing g.AST, or a synthetic/imported board rather than one declared under layers/scenarios/steps in the current file.
Common situations: Editors or automations that build graphs programmatically then try to apply oracle edits to a nested board that was never parsed from the file; passing a boardPath pointing at a board whose source lives in a different .d2 file than the graph's root AST.
Related errors
- board %v AST not found
- failed to recompile: %s %w
- board names cannot contain dots or quotes
- dimensions for object label %#v not found
- dimensions for class field %#v not found
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/cf49eb5f4ba6bf85.
Report an issue: GitHub.