Skip to content

linkcheck reports existing local files as broken when URI contains query or fragment #14542

Description

@SuYanqi

Describe the bug

Linkcheck's local-file validation passes the raw URI (including query and fragment components) directly to a filesystem existence check. As a result, existing local files referenced with ?query or #fragment are incorrectly reported as broken.

For example, target.html exists, but the link target.html?view=full is checked as the literal filename target.html?view=full instead of stripping the query first.

How to Reproduce

import io
import shutil
from pathlib import Path
from sphinx.application import Sphinx

root = Path("/tmp/sphinx_linkcheck_test3")
shutil.rmtree(root, ignore_errors=True)
(root / "_build").mkdir(parents=True)
(root / "target.html").write_text("Target", encoding="utf-8")
(root / "conf.py").write_text("")
(root / "index.rst").write_text(
    "Test\n====\n\n`target <target.html?view=full>`_\n"
)

app = Sphinx(str(root), str(root), str(root / "_build"), str(root / "_doctree"),
             "linkcheck", status=io.StringIO(), warning=io.StringIO())
app.build(force_all=True)
print((root / "_build" / "output.txt").read_text())

Expected: index.rst:4: [working] target.html?view=full
Actual: index.rst:4: [broken] target.html?view=full:

The same issue occurs with fragments (target.html#section) and query-only URIs (?mode=full).

Environment Information

Sphinx: 9.0.4
Python: 3.11.13
Platform: Linux

Sphinx extensions

[]

Additional context

This regression was introduced by PR #7985.

The relevant code at sphinx/builders/linkcheck.py line 475:

if (hyperlink.docpath.parent / uri).exists():

The uri here is the raw string target.html?view=full — it should first strip ? and # suffixes before checking the filesystem.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions