tiangolo/fastapi · error · ValueError
Number of HTML links does not match the number in the origin
Error message
Number of HTML links does not match the number in the original document ({len(links)} vs {len(original_links)}) What it means
Raised by `replace_html_links` (scripts/doc_parsing_utils.py:447) as a ValueError when the number of HTML `<a ...>...</a>` links in a translated document differs from the original English document. As with markdown links, the pipeline rewrites href values positionally, so HTML link counts must match. A mismatch means an HTML link was added, removed, or its tag structure changed so the regex no longer matches.
Source
Thrown at scripts/doc_parsing_utils.py:447
)
return f"<a {attrs_str}>{link_text}</a>"
def replace_html_links(
text: list[str],
links: list[HtmlLinkInfo],
original_links: list[HtmlLinkInfo],
lang_code: str,
) -> list[str]:
"""
Replace HTML links in the given text with the links from the original document.
Adjust URLs for the given language code.
Fail if the number of links does not match the original.
"""
if len(links) != len(original_links):
raise ValueError(
"Number of HTML links does not match the number in the "
"original document "
f"({len(links)} vs {len(original_links)})"
)
modified_text = text.copy()
for link_index, link in enumerate(links):
original_link_info = original_links[link_index]
# Replace in the document text
replacement_link = _construct_html_link(
link_text=link["text"],
attributes=original_link_info["attributes"],
lang_code=lang_code,
)
line_no = link["line_no"] - 1
modified_text[line_no] = modified_text[line_no].replace(
link["full_tag"], replacement_link, 1View on GitHub (pinned to 3e8d1526d8)
Solutions
- Match the count and order of `<a>` tags to the English source.
- Keep `<a>` tags well-formed with at least one attribute after `<a` so the regex matches.
- Do not mix HTML `<a>` links with markdown links when translating; preserve the original format.
Example fix
// before (translation has 1 <a>, English has 2) <a href="/x">x</a> // after <a href="/x">x</a> <a href="/y">y</a>
Defensive patterns
Strategy: validation
Validate before calling
from scripts.doc_parsing_utils import extract_html_links
def html_link_counts_match(translated_lines, en_lines) -> bool:
return len(extract_html_links(translated_lines)) == len(extract_html_links(en_lines)) Type guard
def same_html_link_count(translated_lines, en_lines) -> bool:
from scripts.doc_parsing_utils import extract_html_links
return len(extract_html_links(translated_lines)) == len(extract_html_links(en_lines)) Prevention
- Preserve <a> tags verbatim (count and order) when translating.
- Keep HTML anchors well-formed so the regex matches them.
- Do not convert HTML links to markdown or vice versa.
When it happens
Trigger: Running the docs translation check where a translated file contains a different number of `<a href=...>` tags than the English original. Reformatting an HTML link as markdown or vice versa. A broken/self-closing tag that the `HTML_LINK_RE` regex skips.
Common situations: Translators removing an `<a>` tag or replacing it with markdown syntax. Malformed HTML where a missing attribute breaks the `<a\s+[^>]*>.*?</a>` match. Adding new anchor tags not present in the source.
Related errors
- Number of code include placeholders does not match the numbe
- Number of headers with permalinks does not match the number
- Header levels do not match between document and original doc
- Number of markdown links does not match the number in the or
- Code block (lines {start_line}-{end_line_no}) has different
AI-assisted analysis of tiangolo/fastapi@3e8d1526d8 (2026-08-11).
Data as JSON: /api/errors/636bc9f2cb53bb07.
Report an issue: GitHub.