d2lang/d2 · error

board "%v" not found

Error message

board "%v" not found

What it means

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.

Source

Thrown at d2lsp/d2lsp.go:91

	if err != nil {
		return nil, err
	}

	mfs, err := memfs.New(fs)
	if err != nil {
		return nil, err
	}

	m, _, err := d2ir.Compile(ast, &d2ir.CompileOptions{
		FS: mfs,
	})
	if err != nil {
		return nil, err
	}

	m = m.FindBoardRoot(boardPath)
	if m == nil {
		return nil, fmt.Errorf(`board "%v" not found`, boardPath)
	}
	return m, nil
}

func GetBoardAtPosition(text string, pos d2ast.Position) ([]string, error) {
	r := strings.NewReader(text)
	pos.Byte = -1
	ast, err := d2parser.Parse("", r, nil)
	if err != nil {
		// Even when there is an error, we can still parse broken syntax and perhaps extract something meaningful
		return getBoardPathAtPosition(*ast, nil, pos), err
	}
	return getBoardPathAtPosition(*ast, nil, pos), nil
}

func getBoardPathAtPosition(m d2ast.Map, currPath []string, pos d2ast.Position) []string {
	inRange := func(r d2ast.Range) bool {
		return !pos.Before(r.Start) && pos.Before(r.End)

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Verify each element of boardPath matches a declared board name (case- and whitespace-exact)
  2. List existing boards from the parsed IR before querying and check membership
  3. Load all files that declare the target board into the fs map
  4. Pass an empty boardPath to operate on the root board

Example fix

// before
ranges, _, err := d2lsp.GetRefRanges(key, fs, []string{"layer2"}, m)
// after
boardPath := []string{"layers", "my layer"} // matches actual declaration
ranges, _, err := d2lsp.GetRefRanges(key, fs, boardPath, m)
Defensive patterns

Strategy: validation

Validate before calling

root := m.FindBoardRoot(boardPath)
if root == nil {
	return fmt.Errorf("board %v not declared", boardPath)
}

Try / catch

ranges, _, err := d2lsp.GetRefRanges(key, fs, boardPath, m)
if err != nil && strings.Contains(err.Error(), "board") && strings.Contains(err.Error(), "not found") {
	return fmt.Errorf("board path %v does not exist", boardPath)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31). Data as JSON: /api/errors/8945ccee92262027. Report an issue: GitHub.