Documentation Build Troubleshooting
Last updated: July 22, 2026 Document type: Developer guide
For developers working on SDK documentation: understand common Sphinx/MyST build errors and how to fix them.
Quick diagnostic checklist
Before pushing documentation changes:
# Install dev dependencies
pip install -e ".[dev]"
# Test 1: Run full pre-commit suite (runs locally before commits)
pre-commit run --all-files
# Test 2: Build documentation in strict mode (matches RTD)
python -m sphinx -W --keep-going -b html ./docs ./docs/_build/html-strict
# Test 3: Check markdown syntax
pymarkdown --config .pymarkdown scan README.md GETTING_STARTED.md
# Test 4: Quick validation of key files
python src/britecore_sdk/utils/check_markdown_structure.py
If all tests pass, your changes are ready to commit and push.
Common documentation build errors
Error: “adjacent transitions are not allowed”
Cause: Two or more --- (docutils transition markers) are adjacent with no content between them.
Example (❌ WRONG):
Some paragraph.
---
---
Next section.
Fix:
Some paragraph.
---
Next section.
Prevention:
Review markdown structure visually — each
---should have content both before and after itRun Sphinx build locally before committing:
python -m sphinx -W --keep-going -b html ./docs ./docs/_build/html-strict
Error: “Unknown substitution referenced”
Cause: Reference to a MyST substitution that isn’t defined in docs/conf.py.
Example (❌ WRONG):
Built on {{ unknown_substitution }}
Fix:
Add the substitution to docs/conf.py:
myst_substitutions = {
"docs_version": release,
"unknown_substitution": "value", # ← Add here
}
Prevention:
Only use substitutions defined in
docs/conf.pyCurrent substitutions:
docs_version,docs_commit,docs_commit_date,docs_build_date
Error: “Inline code cannot contain MyST substitutions”
Cause: MyST substitutions don’t expand inside backtick inline code spans.
Example (❌ WRONG):
See `{{ docs_commit }}`
Fix (bare text or separate from code):
See {{ docs_commit }}
Or in code blocks:
\`\`\`
commit: {{ docs_commit }}
\`\`\`
Prevention:
Never wrap MyST substitutions in backticks
Keep substitutions as bare text or inside code fences, not inline code
Error: “Incomplete markup constructs”
Cause: Markdown table syntax is malformed or incomplete.
Example (❌ WRONG):
| Column 1 | Column 2
| --- | ---
| Value 1 | Value 2
Fix:
| Column 1 | Column 2 |
| --- | --- |
| Value 1 | Value 2 |
Prevention:
All table rows must have the same number of columns
Closing
|is required on each rowTest markdown syntax with:
pymarkdown --config .pymarkdown scan FILENAME.md
Error: “Unknown role/directive”
Cause: Using a Sphinx directive or role that isn’t enabled or recognized.
Example (❌ WRONG):
:::{unknown-directive}
Content
:::
Fix: Check if the directive is:
Built-in: Use correct syntax (e.g.,
note,warning,code-block)Extension-based: Verify extension is loaded in
docs/conf.pyCustom: Define in
docs/conf.pyor use existing ones
Prevention:
Check
.rst/MyST documentation for valid directivesVerify extensions in
docs/conf.py:extensions = [...]
Error: “Document title underline too short/too long”
Cause: RST title underlines don’t match the title length.
Example (❌ WRONG):
# Main Title
===
Fix:
# Main Title
=============
Or use markdown-style headings in .md files (MyST handles this automatically):
# Main Title
## Subsection
Prevention:
Use markdown heading syntax (
#,##) in.mdfilesMyST converts these properly to RST for Sphinx
Prevention: Git hooks and pre-commit
Enable pre-commit hooks
Pre-commit hooks automatically validate your changes before committing:
# Install pre-commit framework
pip install pre-commit
# Install hooks from config
pre-commit install
# (Optional) Test hooks on all files
pre-commit run --all-files
What the hooks check
markdown-structure — Python-based markdown validation
pymarkdown — Markdown linting (MD001-MD047 rules)
sphinx-build — Full documentation build with
-W(treat warnings as errors)ruff + black — Code formatting and linting
mypy — Type checking
pytest-unit — Quick unit test smoke check
Bypassing hooks (not recommended)
# Skip all pre-commit checks for one commit
git commit --no-verify
# Run specific hook manually to debug
pre-commit run sphinx-build --verbose
Best practices for documentation changes
Make incremental changes — Edit one section at a time, test with Sphinx build after each section.
Validate before committing — Run full pre-commit suite locally:
pre-commit run --all-files
Structure matters — Review markdown structure visually:
Headings are hierarchical (
#,##,###)Transitions (
---) have content before and afterTables have matching column counts
Code blocks are properly closed
Test locally = test in CI — If it passes locally, it passes CI:
CI runs the same pre-commit hooks
CI runs Sphinx with the same flags (
-W --keep-going)
Use examples from working files — Copy patterns from:
README.md— top-level documentationGETTING_STARTED.md— guide-style documentationdocs/ASYNC_CACHING.md— detailed technical documentation
Document your assumptions — If adding new substitutions, integration points, or event types, update this file too.
Running pre-commit in different scenarios
Before commit (automatic if hooks installed)
git commit -m "message"
# pre-commit runs automatically
Before push (also automatic)
git push origin master
# pre-commit run --hook-stage pre-push runs (release compliance check)
Manual validation (for debugging)
# Check all files
pre-commit run --all-files
# Check specific hook
pre-commit run sphinx-build --all-files
# Dry-run to see what would change
pre-commit run --all-files --verbose
In CI/GitHub Actions
# Runs the same as local: --all-files by default
python -m pre_commit run --all-files