{"record":{"id":"80452462d79443a9","repo":"rust-lang/mdBook","slug":"internal-error-expected-empty-tag-stack-path","errorCode":null,"errorMessage":"internal error: expected empty tag stack.\n\n path: `{}`\nelement={el:?}","messagePattern":"internal error: expected empty tag stack\\.\n\n path: `(.+?)`\nelement=(.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/mdbook-html/src/html/tree.rs","lineNumber":820,"sourceCode":"        }\n        output\n    }\n\n    /// Deals with any unclosed elements on the stack.\n    fn finish_stack(&mut self) {\n        while let Some(node_id) = self.tag_stack.pop() {\n            let node = self.tree.get(node_id).unwrap().value();\n            match node {\n                Node::Fragment => {}\n                Node::Element(el) => {\n                    if el.was_raw {\n                        warn!(\n                            \"unclosed HTML tag `<{}>` found in `{}`\",\n                            el.name.local,\n                            self.options.path.display()\n                        );\n                    } else {\n                        panic!(\n                            \"internal error: expected empty tag stack.\\n\n                             path: `{}`\\n\\\n                             element={el:?}\",\n                            self.options.path.display()\n                        );\n                    }\n                }\n                node => {\n                    panic!(\n                        \"internal error: expected empty tag stack.\\n\n                         path: `{}`\\n\\\n                         node={node:?}\",\n                        self.options.path.display()\n                    );\n                }\n            }\n        }\n    }","sourceCodeStart":802,"sourceCodeEnd":838,"githubUrl":"https://github.com/rust-lang/mdBook/blob/dc21064fc21d955a0e1f67e65e336883c3e5260b/crates/mdbook-html/src/html/tree.rs#L802-L838","documentation":"At the end of processing a document, mdbook-html's finish_stack drains its tag_stack. Leftover Element nodes indicate unclosed HTML tags. If the code cannot safely auto-close them (the branch where it warns about unclosed tags is not taken, e.g. the element type doesn't qualify), it panics that the tag stack should be empty. The panic includes the source path and the leftover element for debugging.","triggerScenarios":"A chapter's event stream ends (process_events calls finish_stack) while an element pushed by start_tag was never popped by a matching end_tag — i.e. unclosed or mismatched HTML tags in markdown source that fall into the non-warned branch.","commonSituations":"Markdown with an opening tag like `<table>` or a custom element that is never closed, tags closed in the wrong nesting order, preprocessors appending HTML without closing tags, or truncated files ending mid-HTML.","solutions":["Open the file shown in the panic (path field) and close every HTML tag you open, in correct order.","Remove stray opening tags that were never intended (e.g. leftover `<div>` from an edit).","Validate chapter HTML with a linter (e.g. htmlhint/tidy) as a preprocessor or CI step.","If a preprocessor generates the HTML, fix it to emit balanced Start/End tag events."],"exampleFix":"// before (src/chapter.md)\n<div class=\"callout\">\nContent...\n\n// after (src/chapter.md)\n<div class=\"callout\">\nContent...\n</div>","handlingStrategy":"validation","validationCode":"// CI check: every opened HTML tag in chapter markdown must be closed\nlet mut open: Vec<String> = vec![];\nfor tag in html_tags_in_file(path)? {\n    match tag {\n        HtmlTag::Open(n) => open.push(n),\n        HtmlTag::Close(n) => { if open.pop().as_deref() != Some(&n) { bail!(\"mismatched tag </{}> in {}\", n, path.display()); } }\n    }\n}\nif !open.is_empty() { bail!(\"unclosed tags {:?} in {}\", open, path.display()); }","typeGuard":null,"tryCatchPattern":"match std::panic::catch_unwind(|| finish_and_render(&mut tree)) {\n    Ok(v) => v,\n    Err(_) => { eprintln!(\"unclosed HTML tag: close all tags in the file named in the panic message\"); std::process::exit(1); }\n}","preventionTips":["Run an HTML linter (tidy/htmlhint) over src/ markdown in CI.","Close every tag you open, in reverse order.","Have preprocessors auto-close emitted tags before finishing."],"tags":["panic","unclosed-tags","malformed-html","markdown"],"backgroundTag":"unclosed-html-tag","analyzedSha":"dc21064fc21d955a0e1f67e65e336883c3e5260b","analyzedAt":"2026-09-01T10:15:12.134Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}