name: sphinx-debug
description: >
Use when make html or sphinx-build fails with
Extension error (sphinx.ext.autosummary),
ImportExceptionGroup, or other Sphinx autosummary / autodoc
import failures. Provides automated pdb diagnosis for
autodoc_mock_imports issues.
Sphinx Debug
Quick Diagnostic Command
Run the build with maximum verbosity and pdb on exception:
make html SPHINXOPTS="-vv -T -P"
Flags:
-vv: Verbose autodoc mock logging-T: Full traceback-P: Drop into pdb on exception
For agents: automate pdb via monkey-patch
If you are an agent and cannot interact with an interactive pdb session,
do not redesign a subprocess/pty capture system. Instead, monkey-patch
pdb.post_mortem so it runs scripted commands and prints the output
directly to stdout.
Run this one-shot script from the docs directory (docs/en or docs/zh_cn):
cd docs/en # or docs/zh_cn
python -c "
import pdb, sys, io, traceback
# Hijack pdb.post_mortem to auto-run diagnostic commands
_original_post_mortem = pdb.post_mortem
def scripted_post_mortem(tb=None):
out = io.StringIO()
p = pdb.Pdb(stdout=out, stdin=io.StringIO(''))
p.use_rawinput = False
p.reset()
if tb is None:
tb = sys.exc_info()[2]
p.setup(None, tb)
old_stderr = sys.stderr
sys.stderr = out
# List all inner exceptions
p.onecmd('for i, exc in enumerate(exceptions): print(f\"[{i}] {type(exc).__name__}: {exc}\")')
# Print full traceback of the first TypeError (the real root cause)
p.onecmd('type_errs = [exc for exc in exceptions if type(exc).__name__ == \"TypeError\"]')
p.onecmd('if type_errs: import traceback; traceback.print_exception(type(type_errs[0]), type_errs[0], type_errs[0].__traceback__)')
p.do_quit('')
sys.stderr = old_stderr
print('=== PDB AUTOMATED OUTPUT ===')
print(out.getvalue())
print('=== END OUTPUT ===')
pdb.post_mortem = scripted_post_mortem
from sphinx.cmd.build import build_main
build_main(['-b', 'html', '-vv', '-T', '-P', '.', '_build/html'])
"
This runs the real Sphinx build with -P, but when pdb drops in it
automatically executes your commands and dumps the results to stdout.
You read the output exactly as if you had typed the pdb commands yourself.
What to look for in the automated output
Sphinx autosummary raises ImportExceptionGroup when it cannot resolve a module.
The top-level message is often misleading (e.g. no module named xtuner.v1.ray.dataflow).
The real root cause is hidden inside the grouped exceptions.
Common root-cause patterns
TypeError about
__version__TypeError: expected string or bytes-like object, got '__version__'This happens when a mocked module (e.g.
torch) is imported for real by an intermediate library (e.g.fla) that callspackaging.version.parse()on the mocked__version__object.Fix: Add the intermediate library to
autodoc_mock_importsinconf.py. To identify the exact library, read the traceback: the frame just abovepackaging/version.pyis the culprit (e.g.fla/utils.py).autodoc_mock_imports = [ ... "fla", # or whatever library triggers the real import ]Missing-comma string-concatenation bug
If
autodoc_mock_importscontains an entry like"scipytorchvision", a comma is missing between two string literals inconf.py:# WRONG autodoc_mock_imports = [ ... "scipy" "torchvision", ... ] # CORRECT autodoc_mock_imports = [ ... "scipy", "torchvision", ... ]AttributeError after the TypeErrors
AttributeError: module 'xtuner.v1.ray' has no attribute 'dataflow'This is usually a secondary failure caused by the earlier
TypeErrors. Fix theTypeErrorfirst, then rebuild.
Step-by-step workflow
- Run the automated pdb script (see "For agents" section above).
- Read the
=== PDB AUTOMATED OUTPUT ===block. - If you see
TypeError: expected string or bytes-like object, got '__version__', read the traceback to find the intermediate library name. - Add the identified library to
autodoc_mock_importsin bothdocs/en/conf.pyanddocs/zh_cn/conf.py. - Also eyeball
autodoc_mock_importsfor missing commas while you are there. - Re-run
make html(without-P) to verify the fix.