{"record":{"id":"8945ccee92262027","repo":"d2lang/d2","slug":"board-v-not-found","errorCode":null,"errorMessage":"board \"%v\" not found","messagePattern":"board \"(.+?)\" not found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2lsp/d2lsp.go","lineNumber":91,"sourceCode":"\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tmfs, err := memfs.New(fs)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tm, _, err := d2ir.Compile(ast, &d2ir.CompileOptions{\n\t\tFS: mfs,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tm = m.FindBoardRoot(boardPath)\n\tif m == nil {\n\t\treturn nil, fmt.Errorf(`board \"%v\" not found`, boardPath)\n\t}\n\treturn m, nil\n}\n\nfunc GetBoardAtPosition(text string, pos d2ast.Position) ([]string, error) {\n\tr := strings.NewReader(text)\n\tpos.Byte = -1\n\tast, err := d2parser.Parse(\"\", r, nil)\n\tif err != nil {\n\t\t// Even when there is an error, we can still parse broken syntax and perhaps extract something meaningful\n\t\treturn getBoardPathAtPosition(*ast, nil, pos), err\n\t}\n\treturn getBoardPathAtPosition(*ast, nil, pos), nil\n}\n\nfunc getBoardPathAtPosition(m d2ast.Map, currPath []string, pos d2ast.Position) []string {\n\tinRange := func(r d2ast.Range) bool {\n\t\treturn !pos.Before(r.Start) && pos.Before(r.End)","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2lsp/d2lsp.go#L73-L109","documentation":"After parsing the file into a d2ir.Map, getBoardMap calls FindBoardRoot(boardPath) to descend to the requested nested board's root map. If the board path does not exist in the compiled IR, nil is returned and this error reports the board path.","triggerScenarios":"Calling d2lsp.GetRefRanges with a boardPath array naming a board (layers/scenarios/steps) that is not declared in the parsed document, e.g. [\"layer2\"] when only layer \"my layer\" exists.","commonSituations":"Referencing boards by the wrong name or order; boards declared in other files not included in fs; renaming/deleting a layer while tooling still references the old board path.","solutions":["Verify each element of boardPath matches a declared board name (case- and whitespace-exact)","List existing boards from the parsed IR before querying and check membership","Load all files that declare the target board into the fs map","Pass an empty boardPath to operate on the root board"],"exampleFix":"// before\nranges, _, err := d2lsp.GetRefRanges(key, fs, []string{\"layer2\"}, m)\n// after\nboardPath := []string{\"layers\", \"my layer\"} // matches actual declaration\nranges, _, err := d2lsp.GetRefRanges(key, fs, boardPath, m)","handlingStrategy":"validation","validationCode":"root := m.FindBoardRoot(boardPath)\nif root == nil {\n\treturn fmt.Errorf(\"board %v not declared\", boardPath)\n}","typeGuard":null,"tryCatchPattern":"ranges, _, err := d2lsp.GetRefRanges(key, fs, boardPath, m)\nif err != nil && strings.Contains(err.Error(), \"board\") && strings.Contains(err.Error(), \"not found\") {\n\treturn fmt.Errorf(\"board path %v does not exist\", boardPath)\n}","preventionTips":["Mirror board names exactly as declared (layers/scenarios/steps)","Discover valid board paths from the IR instead of hardcoding","Load all files contributing boards into fs before querying"],"tags":["d2","lsp","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"}