{"record":{"id":"9b98f43634d4e48e","repo":"docling-project/docling","slug":"an-internal-error-has-occurred-during-markdown-con","errorCode":null,"errorMessage":"An internal error has occurred during Markdown conversion.","messagePattern":"An internal error has occurred during Markdown conversion\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"docling/backend/md_backend.py","lineNumber":815,"sourceCode":"                doc=doc,\n                parent_item=None,\n                visited=set(),\n                creation_stack=[],\n                list_ordered_flag_by_ref={},\n                list_last_item_by_ref={},\n            )\n            self._close_table(doc=doc)  # handle any last hanging table\n\n            # if HTML blocks were detected, export to HTML and delegate to HTML backend\n            if self._html_blocks > 0:\n                # export to HTML\n                html_backend_cls = HTMLDocumentBackend\n                html_str = doc.export_to_html()\n\n                def _restore_original_html(txt, regex):\n                    _txt, count = re.subn(regex, \"\", txt)\n                    if count != self._html_blocks:\n                        raise RuntimeError(\n                            \"An internal error has occurred during Markdown conversion.\"\n                        )\n                    return _txt\n\n                # restore original HTML by removing previously added markers\n                for regex in [\n                    rf\"<pre>\\s*<code>\\s*{_START_MARKER}\",\n                    rf\"{_STOP_MARKER}\\s*</code>\\s*</pre>\",\n                ]:\n                    html_str = _restore_original_html(txt=html_str, regex=regex)\n                self._html_blocks = 0\n                # delegate to HTML backend\n                stream = BytesIO(bytes(html_str, encoding=\"utf-8\"))\n                md_options = cast(MarkdownBackendOptions, self.options)\n                html_options = HTMLBackendOptions(\n                    enable_local_fetch=md_options.enable_local_fetch,\n                    enable_remote_fetch=md_options.enable_remote_fetch,\n                    fetch_images=md_options.fetch_images,","sourceCodeStart":797,"sourceCodeEnd":833,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/backend/md_backend.py#L797-L833","documentation":"Internal RuntimeError raised while converting Markdown that embeds raw HTML blocks. During parsing, HTML blocks are wrapped in _START_MARKER/_STOP_MARKER sentinels so they survive into the intermediate document; after export to HTML the backend strips them again with two regex substitutions. If the number of regex matches (re.subn count) does not equal self._html_blocks, marker insertion and removal got out of sync — an invariant violation inside the MD→HTML delegation path, not something the input file controls directly.","triggerScenarios":"Converting a .md file whose HTML blocks, after marker wrapping and doc.export_to_html(), produce HTML where the `<pre><code>` + marker pattern is merged, duplicated, or altered (e.g. HTML blocks containing code-fence-like content, nested markers, or exporter changes that reformat `<pre><code>` whitespace). re.subn then matches a different count of markers than were inserted.","commonSituations":"Markdown with raw `<div>`/`<table>`/`<pre>` HTML blocks, especially ones containing literal `<code>` tags or content that the HTML exporter reindents. Also appears after upgrading docling when export_to_html() output formatting changed while md_backend marker handling did not.","solutions":["Report it as a docling bug with the minimal .md file that reproduces it — the marker-count invariant is internal to md_backend.py.","As a workaround, strip or fence the raw HTML blocks in the input (wrap them in ``` fences) so the HTML-delegation path is not taken.","Try a different docling version: the interaction between export_to_html() formatting and the marker regexes is version-dependent.","If you control the input pipeline, normalize HTML blocks (e.g. pre-convert MD HTML to plain markdown) before conversion."],"exampleFix":"# before (raw HTML block triggers marker path)\n<div class=\"note\">hello <code>world</code></div>\n\n# after (fenced, bypasses HTML block detection)\n```html\n<div class=\"note\">hello <code>world</code></div>\n```","handlingStrategy":"try-catch","validationCode":"import re\n\ndef has_risky_html_blocks(md_text: str) -> bool:\n    # raw HTML lines (not fenced) that also contain code/pre markers\n    risky = re.findall(r'(?m)^(?!`{3,}).*?<(?:pre|code|div)[^>]*>.*$', md_text)\n    return any('<code' in b or '<pre' in b for b in risky)","typeGuard":null,"tryCatchPattern":"try:\n    doc = converter.convert(md_path)\nexcept RuntimeError as e:\n    if 'internal error has occurred during Markdown conversion' in str(e):\n        doc = converter.convert(sanitize_html_blocks(md_path))  # fence raw HTML first\n    else:\n        raise","preventionTips":["Wrap raw HTML in fenced code blocks when authoring Markdown destined for docling.","Pin a docling version regression-tested against your HTML-heavy Markdown corpus.","Keep a corpus smoke test that exercises MD files containing inline HTML."],"tags":["markdown","html","internal-error","regex"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}