{"record":{"id":"5991141f739ebf25","repo":"swc-project/swc","slug":"strayendtag","errorCode":"StrayEndTag","errorMessage":"Stray end tag \"{tag_name}\"","messagePattern":"Stray end tag \"(.+?)\"","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"crates/swc_html_parser/src/parser/mod.rs","lineNumber":1647,"sourceCode":"                    Token::StartTag { tag_name, .. } if tag_name == \"head\" => {\n                        let element = self.insert_html_element(token_and_info)?;\n\n                        self.head_element_pointer = Some(element);\n                        self.insertion_mode = InsertionMode::InHead;\n                    }\n                    // An end tag whose tag name is one of: \"head\", \"body\", \"html\", \"br\"\n                    //\n                    // Act as described in the \"anything else\" entry below.\n                    Token::EndTag { tag_name, .. }\n                        if matches!(&**tag_name, \"head\" | \"body\" | \"html\" | \"br\") =>\n                    {\n                        anything_else(self, token_and_info)?;\n                    }\n                    // Any other end tag\n                    //\n                    // Parse error. Ignore the token.\n                    Token::EndTag { tag_name, .. } => {\n                        self.errors.push(Error::new(\n                            token_and_info.span,\n                            ErrorKind::StrayEndTag(tag_name.clone()),\n                        ));\n                    }\n                    // Anything else\n                    //\n                    // Insert an HTML element for a \"head\" start tag token with no attributes.\n                    //\n                    // Set the head element pointer to the newly created head element.\n                    //\n                    // Switch the insertion mode to \"in head\".\n                    //\n                    // Reprocess the current token.\n                    _ => {\n                        anything_else(self, token_and_info)?;\n                    }\n                }\n            }","sourceCodeStart":1629,"sourceCodeEnd":1665,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_html_parser/src/parser/mod.rs#L1629-L1665","documentation":"In the 'before head' insertion mode (crates/swc_html_parser/src/parser/mod.rs:1647), any end tag other than head/body/html/br is a parse error (StrayEndTag) and is ignored. The parser is past <html> but has not built <head> yet, so such closers match nothing.","triggerScenarios":"An end tag directly following the html start tag with no head started: `<html></div>`, `<html>\\n</span>text`. The four exceptional names (head/body/html/br) take the 'anything else' path that implicitly creates <head>.","commonSituations":"Layout templates with stray closers left in the pre-head region, trimmed partials pasted after an explicit <html>, hand-written document shells.","solutions":["Remove the stray end tag from the region between <html> and the first head/body content","Let the parser auto-create head/body and place markup there","Filter ErrorKind::StrayEndTag(_) if pre-head junk is tolerated"],"exampleFix":"<!-- before -->\n<html>\n  </div>\n  <p>x</p>\n</html>\n\n<!-- after -->\n<html>\n  <p>x</p>\n</html>","handlingStrategy":"validation","validationCode":"fn end_tag_before_head(html: &str) -> Option<usize> {\n    let lower = html.to_ascii_lowercase();\n    let html_end = lower.find(\"<html\").map(|i| i + 5)?;\n    let head = lower.find(\"<head\").unwrap_or(lower.len());\n    lower[html_end..head].find(\"</\").map(|i| html_end + i)\n}","typeGuard":null,"tryCatchPattern":"use swc_html_parser::error::ErrorKind;\n\nlet mut errors = Vec::new();\nlet doc = swc_html_parser::parse_file_as_document(&fm, config, &mut errors)?;\n\nfor err in &errors {\n    if let ErrorKind::StrayEndTag(tag) = err.kind() {\n        log::warn!(\"end tag </{}> before <head> ignored\", tag);\n    }\n}","preventionTips":["Keep the region between <html> and head content free of stray markup","Generate document shells from one tested template","Treat pre-head orphan closers as shell-template bugs"],"tags":["html","parser","end-tag","orphan","insertion-mode","swc"],"backgroundTag":"stray-end-tag","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}