{"record":{"id":"ea775665977f167a","repo":"d2lang/d2","slug":"board-v-not-found-ea7756","errorCode":null,"errorMessage":"board %v not found","messagePattern":"board (.+?) not found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2oracle/edit.go","lineNumber":41,"sourceCode":")\n\ntype OutsideScopeError struct{}\n\nfunc (e OutsideScopeError) Error() string {\n\treturn \"operation would modify AST outside of given scope\"\n}\n\nfunc Create(g *d2graph.Graph, boardPath []string, key string) (_ *d2graph.Graph, newKey string, err error) {\n\tdefer xdefer.Errorf(&err, \"failed to create %#v\", key)\n\n\tboardG := g\n\tbaseAST := g.AST\n\n\tif len(boardPath) > 0 {\n\t\t// When compiling a nested board, we can read from boardG but only write to baseBoardG\n\t\tboardG = GetBoardGraph(g, boardPath)\n\t\tif boardG == nil {\n\t\t\treturn nil, \"\", fmt.Errorf(\"board %v not found\", boardPath)\n\t\t}\n\t\t// TODO beter name\n\t\tbaseAST = boardG.BaseAST\n\t\tif baseAST == nil {\n\t\t\treturn nil, \"\", fmt.Errorf(\"board %v cannot be modified through this file\", boardPath)\n\t\t}\n\t}\n\n\tnewKey, edge, err := generateUniqueKey(boardG, key, nil, nil)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\n\tif edge {\n\t\terr = _set(boardG, baseAST, key, nil, nil)\n\t} else {\n\t\terr = _set(boardG, baseAST, newKey, nil, nil)\n\t}","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2oracle/edit.go#L23-L59","documentation":"d2oracle.Create can edit a nested board only if GetBoardGraph can locate it in the multi-board graph. When boardPath names a board that does not exist, boardG is nil and Create returns this error instead of producing an edit operation.","triggerScenarios":"Calling d2oracle.Create(g, boardPath, name) where boardPath is a non-empty slice whose board cannot be found via GetBoardGraph — wrong board names, board not compiled into g, or board declared in another file.","commonSituations":"Oracle-based tooling (editors, generators) targeting layers/scenarios/steps after they were renamed; building boardPath from user input without validating board existence; boards loaded from separate files absent from g.","solutions":["Validate the board exists first with GetBoardGraph(g, boardPath) before calling Create","Match boardPath names exactly to declared layers/scenarios/steps in the compiled graph","Pass nil/empty boardPath to edit the root board instead","Recompile the full multi-board graph so all boards are present in g"],"exampleFix":"// before\nop, err := d2oracle.Create(g, []string{\"layers\", \"newLayer\"}, \"x\")\n// after\nif d2oracle.GetBoardGraph(g, []string{\"layers\", \"newLayer\"}) == nil {\n\treturn errors.New(\"board does not exist; create it first\")\n}\nop, err := d2oracle.Create(g, []string{\"layers\", \"newLayer\"}, \"x\")","handlingStrategy":"validation","validationCode":"if len(boardPath) > 0 && d2oracle.GetBoardGraph(g, boardPath) == nil {\n\treturn fmt.Errorf(\"board %v does not exist\", boardPath)\n}","typeGuard":"func boardExists(g *d2graph.Graph, boardPath []string) bool {\n\treturn len(boardPath) == 0 || d2oracle.GetBoardGraph(g, boardPath) != nil\n}","tryCatchPattern":"op, _, err := d2oracle.Create(g, boardPath, name)\nif err != nil && strings.Contains(err.Error(), \"board\") && strings.Contains(err.Error(), \"not found\") {\n\treturn fmt.Errorf(\"create the board before editing: %w\", err)\n}","preventionTips":["Check GetBoardGraph for nil before any oracle edit on nested boards","Keep boardPath derived from the compiled graph's actual board structure","Recompile the full graph after creating/renaming boards so oracle sees them"],"tags":["d2","oracle","board","not-found"],"backgroundTag":"board-not-found","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}