Skip to content

Fix AssertionError when confval default contains cross-reference - #14643

Draft
aryansk wants to merge 1 commit into
sphinx-doc:masterfrom
aryansk:fix-confval-default-ref-14117
Draft

Fix AssertionError when confval default contains cross-reference#14643
aryansk wants to merge 1 commit into
sphinx-doc:masterfrom
aryansk:fix-confval-default-ref-14117

Conversation

@aryansk

@aryansk aryansk commented Aug 25, 2026

Copy link
Copy Markdown

Problem

Given a file like:

.. confval:: conf1

   Description of conf1.

.. confval:: conf2
   :default: Fallback to :confval:`conf1`

   Description of conf2.

The build crashes with:

File .../sphinx/writers/html5.py, line 342, in visit_reference
    assert len(node) == 1 and isinstance(node[0], nodes.image)
AssertionError

Same happens with :envvar: inside :default: (e.g. .. confval:: conf1 :default: :envvar:ENV1``). The problem is any cross-reference in :default: or `:type:` when the target exists.

Fixes #14117

Change

In sphinx/domains/std/__init__.py, ConfigurationValue.format_type and format_default previously did:

parsed, msgs = self.parse_inline(default, ...)
field_body('', *parsed)

parse_inline returns inline nodes (Text + pending_xref/reference) directly. Placing them directly into field_body means a reference's parent is field_body (not a TextElement). The HTML5 writer then asserts:

if not isinstance(node.parent, nodes.TextElement):
    assert len(node) == 1 and isinstance(node[0], nodes.image)

— expecting only image references outside TextElement. Wrapping the parsed nodes in a paragraph (which is a TextElement) fixes the hierarchy:

field_body('', paragraph('', '', *parsed))

Single-file, 2-line fix covering both :type: and :default:.

Why this approach

field_body is defined to hold block elements; normal field_list entries wrap inline content in a paragraph. The confval :type:/:default: fields were the outlier. Adding the paragraph matches the rest of the codebase and fixes the writer assert without touching the writer itself (which correctly distinguishes image vs text references).

Testing

command: uv run --project /tmp/sphinx-ops072-l1/repo python /tmp/test_confval3.py
result: Build succeeded, HTML contains conf1, no AssertionError; second test with :envvar: also PASS

command: uv run --project /tmp/sphinx-ops072-l1/repo pytest tests/test_domains/test_domain_std.py -v
result: 20 passed

command: git diff --check
result: clean

Documentation and release impact

  • No docs impact (bug fix)
  • Changelog — will add if requested

Review notes

  • Follow-up: none
  • Security: no

AI disclosure

Muse Spark assisted in analysis and drafting; all changes reviewed and tested manually. Co-authored-by trailers included for Pair Extraordinaire.

Co-authored-by: Muse Spark muse-spark@users.noreply.github.com
Co-authored-by: Aryan Singh K 70511529+aryansk@users.noreply.github.com

The confval directive's :default: option is formatted via parse_inline
into a field_body. Previously it placed inline nodes directly into
field_body, so a reference like :confval:`conf1` inside
:default: had a parent of field_body (not a TextElement). The HTML
writer then hit the assert for non-TextElement parents:

  assert len(node) == 1 and isinstance(node[0], nodes.image)

Wrapping the parsed inline nodes in a paragraph (a TextElement)
fixes the structure, so references are inside a paragraph inside
field_body, matching normal field handling.

Fixes sphinx-doc#14117

Co-authored-by: Muse Spark <muse-spark@users.noreply.github.com>
Co-authored-by: Aryan Singh K <70511529+aryansk@users.noreply.github.com>

AI disclosure: Muse Spark assisted in analysis and fix drafting;
changes reviewed and tested manually (reproduction with
:confval: in :default: now builds, HTML contains link, 20
test_domain_std tests pass).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AssertionError when using a :confval: reference inside a .. confval :default:

1 participant