{"record":{"id":"0ce885132c37cc9d","repo":"tiangolo/fastapi","slug":"number-of-markdown-links-does-not-match-the-number","errorCode":null,"errorMessage":"Number of markdown links does not match the number in the original document ({len(links)} vs {len(original_links)})","messagePattern":"Number of markdown links does not match the number in the original document \\((.+?) vs (.+?)\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scripts/doc_parsing_utils.py","lineNumber":323,"sourceCode":"        link += f\"{{{attributes}}}\"\n\n    return link\n\n\ndef replace_markdown_links(\n    text: list[str],\n    links: list[MarkdownLinkInfo],\n    original_links: list[MarkdownLinkInfo],\n    lang_code: str,\n) -> list[str]:\n    \"\"\"\n    Replace markdown links in the given text with the original links.\n\n    Fail if the number of links does not match the original.\n    \"\"\"\n\n    if len(links) != len(original_links):\n        raise ValueError(\n            \"Number of markdown links does not match the number in the \"\n            \"original document \"\n            f\"({len(links)} vs {len(original_links)})\"\n        )\n\n    modified_text = text.copy()\n    for i, link_info in enumerate(links):\n        link_text = link_info[\"text\"]\n        link_title = link_info[\"title\"]\n        original_link_info = original_links[i]\n\n        # Replace\n        replacement_link = _construct_markdown_link(\n            url=original_link_info[\"url\"],\n            text=link_text,\n            title=link_title,\n            attributes=original_link_info[\"attributes\"],\n            lang_code=lang_code,","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/tiangolo/fastapi/blob/3e8d1526d83a90aaf7d6eb6dc682bf150f180b25/scripts/doc_parsing_utils.py#L305-L341","documentation":"Raised by `replace_markdown_links` (scripts/doc_parsing_utils.py:323) as a ValueError when the number of markdown links `[text](url)` found in a translated document differs from the original English document. The translation pipeline rewrites link URLs (e.g. injecting a language code) using positional correspondence, so the link counts must match; a mismatch means a link was added, removed, or escaped differently.","triggerScenarios":"Running the docs translation check on a file where a translator removed a link, converted `[text](url)` to plain text, or added a new link. An image `![alt](url)` was turned into a link, or a link escaped as `\\[...\\]` incorrectly.","commonSituations":"Translators dropping links they deemed irrelevant. Splitting/merging paragraphs that changed link count. Escape-character differences (`\\[` vs `[`). Links wrapped differently across line breaks.","solutions":["Restore the same number of markdown links as the English source, in the same order.","Keep `![images](url)` distinct from text links; do not convert one into the other.","Re-sync the translation from the latest English doc to recover link structure."],"exampleFix":"// before (translation has 1 link, English has 2)\nSee [docs](/docs).\n// after\nSee [docs](/docs) and [tutorial](/tutorial).","handlingStrategy":"validation","validationCode":"from scripts.doc_parsing_utils import extract_markdown_links\n\ndef markdown_link_counts_match(translated_lines, en_lines) -> bool:\n    return len(extract_markdown_links(translated_lines)) == len(extract_markdown_links(en_lines))","typeGuard":"def same_markdown_link_count(translated_lines, en_lines) -> bool:\n    from scripts.doc_parsing_utils import extract_markdown_links\n    return len(extract_markdown_links(translated_lines)) == len(extract_markdown_links(en_lines))","tryCatchPattern":null,"preventionTips":["Preserve every markdown link (same count and order) when translating.","Keep images ![..](..) and links [..](..) distinct.","Do not escape links with backslashes unless the source does."],"tags":["fastapi","docs","translation","ci","validation"],"backgroundTag":null,"analyzedSha":"3e8d1526d83a90aaf7d6eb6dc682bf150f180b25","analyzedAt":"2026-08-11T02:34:52.986Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}