{"record":{"id":"f7a89288894974c2","repo":"tiangolo/fastapi","slug":"code-block-lines-start-line-end-line-no-has","errorCode":null,"errorMessage":"Code block (lines {start_line}-{end_line_no}) has different language than the original block ('{block_a['lang']}' vs '{block_b['lang']}')","messagePattern":"Code block \\(lines (.+?)-(.+?)\\) has different language than the original block \\('(.+?)' vs '(.+?)'\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scripts/doc_parsing_utils.py","lineNumber":584,"sourceCode":"        return code, comment\n    return line, None\n\n\ndef replace_multiline_code_block(\n    block_a: MultilineCodeBlockInfo, block_b: MultilineCodeBlockInfo\n) -> list[str]:\n    \"\"\"\n    Replace multiline code block `a` with block `b` leaving comments intact.\n\n    Syntax of comments depends on the language of the code block.\n    Raises ValueError if the blocks are not compatible (different languages or different number of lines).\n    \"\"\"\n\n    start_line = block_a[\"start_line_no\"]\n    end_line_no = start_line + len(block_a[\"content\"]) - 1\n\n    if block_a[\"lang\"] != block_b[\"lang\"]:\n        raise ValueError(\n            f\"Code block (lines {start_line}-{end_line_no}) \"\n            \"has different language than the original block \"\n            f\"('{block_a['lang']}' vs '{block_b['lang']}')\"\n        )\n    if len(block_a[\"content\"]) != len(block_b[\"content\"]):\n        raise ValueError(\n            f\"Code block (lines {start_line}-{end_line_no}) \"\n            \"has different number of lines than the original block \"\n            f\"({len(block_a['content'])} vs {len(block_b['content'])})\"\n        )\n\n    block_language = block_a[\"lang\"].lower()\n    if block_language in {\"mermaid\"}:\n        if block_a != block_b:\n            print(\n                f\"Skipping mermaid code block replacement (lines {start_line}-{end_line_no}). \"\n                \"This should be checked manually.\"\n            )","sourceCodeStart":566,"sourceCodeEnd":602,"githubUrl":"https://github.com/tiangolo/fastapi/blob/3e8d1526d83a90aaf7d6eb6dc682bf150f180b25/scripts/doc_parsing_utils.py#L566-L602","documentation":"Raised by `replace_multiline_code_block` (scripts/doc_parsing_utils.py:584) as a ValueError when a fenced code block in the translated document has a different language tag (the token after ```) than the corresponding block in the English original. The pipeline replaces code content while preserving comments from the translation, but only within blocks of the same language; a language mismatch signals the blocks are not equivalent.","triggerScenarios":"Running the docs translation check where a translator changed ```python to ```py, or ```bash to ```sh, or renamed ```Python (case difference matters since comparison is case-insensitive but the token must still parse). A block re-tagged to ```text or ```json. Blocks out of order so a different block is paired positionally.","commonSituations":"Inconsistent language aliases (py vs python) between translation and source. Translators 'fixing' the language hint. Adding/removing code blocks so positional pairing aligns the wrong blocks. Case differences are tolerated only after `.lower()`, but token presence still must match.","solutions":["Use the identical language token (e.g. ```python) on the translated block as on the English block.","Keep the same number and order of fenced code blocks so pairing is correct.","Avoid re-tagging blocks; if a different language is genuinely needed, update both source and translation together."],"exampleFix":"// before (English: ```python, translation: ```py)\n```py\nx = 1\n```\n// after\n```python\nx = 1\n```","handlingStrategy":"validation","validationCode":"from scripts.doc_parsing_utils import extract_multiline_code_blocks\n\ndef code_block_langs_match(translated_lines, en_lines) -> bool:\n    a = extract_multiline_code_blocks(translated_lines)\n    b = extract_multiline_code_blocks(en_lines)\n    return len(a) == len(b) and all(x['lang'].lower() == y['lang'].lower() for x, y in zip(a, b))","typeGuard":"def corresponding_blocks_same_lang(translated_lines, en_lines) -> bool:\n    from scripts.doc_parsing_utils import extract_multiline_code_blocks\n    a = extract_multiline_code_blocks(translated_lines)\n    b = extract_multiline_code_blocks(en_lines)\n    return len(a) == len(b) and all(x['lang'].lower() == y['lang'].lower() for x, y in zip(a, b))","tryCatchPattern":null,"preventionTips":["Copy the exact language token (e.g. python, not py) from the English block.","Keep the same number and order of fenced code blocks in translations.","Do not re-tag code blocks; update source and translation together if a language must change."],"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"}