{"record":{"id":"37fb08bc41b238bb","repo":"rust-lang/mdBook","slug":"pop-too-far-processing","errorCode":null,"errorMessage":"pop too far processing `{}`","messagePattern":"pop too far processing `(.+?)`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/mdbook-html/src/html/tree.rs","lineNumber":283,"sourceCode":"        self.current_node = new_node;\n    }\n\n    /// Append a new child to the current node, and make the new node the current node.\n    ///\n    /// As compared to `push`, it is *not* expected that there will be a `pop` called\n    /// for this node. The next call to `pop` will unwind the stack past this node.\n    fn push_no_stack(&mut self, node: Node) {\n        let new_node = self.append(node);\n        self.current_node = new_node;\n    }\n\n    /// Switch the current node to the current node's parent.\n    fn pop(&mut self) {\n        self.tag_stack.pop();\n        if let Some(&parent) = self.tag_stack.last() {\n            self.current_node = parent;\n        } else {\n            panic!(\"pop too far processing `{}`\", self.options.path.display());\n        }\n    }\n\n    /// Returns all of the [`NodeId`]s, filtering out just the [`Element`]\n    /// nodes where the given callback returns `true` based on the element\n    /// name.\n    fn node_ids_for_tag(&self, filter: &dyn Fn(&str) -> bool) -> Vec<NodeId> {\n        self.tree\n            .nodes()\n            .filter(|node| {\n                let Node::Element(el) = node.value() else {\n                    return false;\n                };\n                filter(el.name())\n            })\n            .map(|node| node.id())\n            .collect()\n    }","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/rust-lang/mdBook/blob/dc21064fc21d955a0e1f67e65e336883c3e5260b/crates/mdbook-html/src/html/tree.rs#L265-L301","documentation":"mdbook-html builds a DOM tree from markdown/pulldown-cmark events using a tag_stack; pop() removes the current element and moves to its parent. If pop() is called when only the root remains on the stack, the stack would underflow, so the code panics with this message including the source file path. It means the event stream was unbalanced — an End event arrived with no matching Start.","triggerScenarios":"An unbalanced markdown event stream while processing events: an end_tag/start_tag/footnote_reference sequence that pops more times than it pushed, e.g. stray closing tags in inline HTML passed through to the renderer, or a footnote reference processed outside of any open element.","commonSituations":"Markdown containing malformed inline HTML with unmatched closing tags (e.g. `</div>` with no opener), plugins/preprocessors injecting unbalanced HTML into chapter content, or a bug in a custom pulldown-cmark event filter that drops Start events but keeps End events.","solutions":["Find and fix the unbalanced HTML/markdown in the file named in the panic message (options.path).","Run any custom preprocessors' output through an HTML validator to ensure tags are balanced.","Check pulldown-cmark version compatibility: an event-consumption change in the parser can leave streams unbalanced; pin/upgrade the parser version consistently.","If caused by a preprocessor, fix it to emit a Start for every End tag it emits."],"exampleFix":"// before (src/chapter.md)\nsome text\n</div>\n\n// after (src/chapter.md)\n<div>\nsome text\n</div>","handlingStrategy":"validation","validationCode":"// preprocessor-side: verify balanced tag emission before passing events on\nlet mut depth = 0i32;\nfor ev in &events {\n    match ev {\n        Event::Start(_) => depth += 1,\n        Event::End(_) => { depth -= 1; assert!(depth >= 0, \"unbalanced End event\"); }\n        _ => {}\n    }\n}","typeGuard":null,"tryCatchPattern":"std::panic::catch_unwind(|| render_book(&book)).unwrap_or_else(|_| {\n    eprintln!(\"render panicked: inspect the file in the panic path for unbalanced HTML tags\");\n    std::process::exit(1);\n});","preventionTips":["Lint markdown files for unmatched closing tags (e.g. stray </div>).","Ensure preprocessors emit one End for every Start.","Keep pulldown-cmark versions aligned across mdbook and plugins."],"tags":["panic","html-parsing","malformed-html","markdown"],"backgroundTag":"unbalanced-tag-stack","analyzedSha":"dc21064fc21d955a0e1f67e65e336883c3e5260b","analyzedAt":"2026-09-01T10:15:12.134Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}