Skip to content

Fix crash when toc references a missing file#3469

Open
cotti wants to merge 1 commit into
mainfrom
fix/3245-missing-toc-file-nre
Open

Fix crash when toc references a missing file#3469
cotti wants to merge 1 commit into
mainfrom
fix/3245-missing-toc-file-nre

Conversation

@cotti
Copy link
Copy Markdown
Contributor

@cotti cotti commented Jun 5, 2026

Why

Running docs-builder build/serve on a docset whose toc references a Markdown file that doesn't exist on disk crashed with an unhandled NullReferenceException while building navigation lookups, instead of reporting a clear validation error. The validation error was actually already computed — the process just died on an unguarded null dereference before it could be shown.

Closes #3245.

What

When a TOC entry resolves to a file the factory can't create, that nav item is dropped. If a node ends up with zero items, its Index is set to a null! sentinel. Because INodeNavigationItem<out TIndex, …> is covariant, the root node matches the INodeNavigationItem<IDocumentationFile, …> branch in both BuildNavigationLookups and DocumentationSet.VisitNavigation, where Index.Model was dereferenced unconditionally → the reported NRE.

This change:

  • Guards the null Index sentinel at both dereference sites, so the build no longer crashes and the already-emitted validation error surfaces, exiting cleanly.
  • Clarifies the diagnostic to say whether the referenced file is missing on disk or exists but isn't a valid Markdown document, anchored to the docset.yml location.
  • Adds a Navigation.Tests case that drives BuildNavigationLookups with a missing-file TOC and asserts it does not throw and emits a clear error (the existing validation tests never exercised this path).

Verified end-to-end: a docset with a missing file: entry now prints Table of contents references '…' but the file does not exist on disk. and exits with an error rather than crashing.

Made with Cursor

A `toc` entry pointing at a Markdown file that doesn't exist on disk
caused the navigation builder to leave the root node's `Index` as a
`null!` sentinel. `BuildNavigationLookups` (and `VisitNavigation` with
extensions enabled) then dereferenced that sentinel via the covariant
`INodeNavigationItem<IDocumentationFile, ...>` branch, throwing an
unhandled `NullReferenceException` before the already-computed
validation error could surface.

Guard the null `Index` sentinel at both dereference sites so the build
exits cleanly and reports the error. Also clarify the diagnostic to
state whether the referenced file is missing on disk or not a valid
Markdown document, anchored to the docset.yml location.

Closes #3245

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 5, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0e8bea9d-ffca-4db4-b92b-eafb01cde2c2

📥 Commits

Reviewing files that changed from the base of the PR and between d115285 and 9b98d13.

📒 Files selected for processing (5)
  • src/Elastic.Documentation.Navigation/Isolated/Node/DocumentationSetNavigation.cs
  • src/Elastic.Documentation.Navigation/NavigationItemExtensions.cs
  • src/Elastic.Markdown/IO/DocumentationSet.cs
  • tests/Navigation.Tests/Isolation/ValidationTests.cs
  • tests/Navigation.Tests/TestDocumentationSetContext.cs

📝 Walkthrough

Walkthrough

This PR fixes a NullReferenceException that occurred when a docset's TOC referenced a missing markdown file. The fix introduces a null sentinel to represent missing files during navigation construction, allowing the system to emit a diagnostic error instead of crashing. The changes refactor the file-creation error contract to distinguish missing files from invalid Markdown, update navigation building and visiting to handle null Index values safely, and add test coverage to prevent regression.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix crash when toc references a missing file' directly and clearly summarizes the main change—preventing a NullReferenceException crash when a TOC entry points to a non-existent file.
Description check ✅ Passed The description is well-related to the changeset, explaining the root cause (null Index sentinel dereference), the fix (null guards at dereference sites), and verification that the error now surfaces cleanly instead of crashing.
Linked Issues check ✅ Passed All primary objectives from issue #3245 are met: the crash is prevented by guarding null dereference sites [DocumentationSetNavigation.cs, NavigationItemExtensions.cs, DocumentationSet.cs], clear diagnostics are emitted [DocumentationSetNavigation.cs], and test coverage is added [ValidationTests.cs, TestDocumentationSetContext.cs].
Out of Scope Changes check ✅ Passed All changes directly address the crash fix: null guards in navigation lookup construction, improved error messages distinguishing missing vs. invalid files, and a focused test case exercising the missing-file path.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/3245-missing-toc-file-nre

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NullReferenceException in navigation when TOC references a missing file

1 participant