swc-project/swc · warning · swc_html_parser::error::Error
End tag "{end_tag_name}" did not match the name of the curre
Error message
End tag "{end_tag_name}" did not match the name of the current open element ("{current_element_tag_name}") What it means
An end tag `</br>` or `</p>` was processed while the current node was a foreign (SVG/MathML) element (crates/swc_html_parser/src/parser/mod.rs:807). The parser reports EndTagDidNotMatchCurrentOpenElement with the innermost open element's name, runs pop_until_in_foreign(), and reprocesses the token with HTML rules. The HTML element named by the end tag was never open in the foreign subtree.
Source
Thrown at crates/swc_html_parser/src/parser/mod.rs:807
tag_name,
attributes,
..
} if tag_name == "font"
&& attributes
.iter()
.any(|attribute| matches!(&*attribute.name, "color" | "face" | "size")) =>
{
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::HtmlStartTagInForeignContext(tag_name.clone()),
));
self.open_elements_stack.pop_until_in_foreign();
self.process_token(token_and_info, None)?;
}
Token::EndTag { tag_name, .. } if matches!(&**tag_name, "br" | "p") => {
let last = get_tag_name!(self.open_elements_stack.items.last().unwrap());
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::EndTagDidNotMatchCurrentOpenElement(tag_name.clone(), last.into()),
));
self.open_elements_stack.pop_until_in_foreign();
self.process_token(token_and_info, None)?;
}
// Any other start tag
//
// If the adjusted current node is an element in the MathML namespace, adjust MathML
// attributes for the token. (This fixes the case of MathML attributes that are not all
// lowercase.)
//
// If the adjusted current node is an element in the SVG namespace, and the token's tag
// name is one of the ones in the first column of the following table, change the tag
// name to the name given in the corresponding cell in the second column. (This fixes
// the case of SVG elements that are not all lowercase.)
//
// Tag name Element nameView on GitHub (pinned to 5176682b65)
Solutions
- Balance the end tag: close <p> where it was opened, outside the foreign subtree
- Fix the unclosed <svg>/<math> so following end tags are handled by HTML rules
- Treat the error as informational when the auto-close-and-reprocess recovery is acceptable
Example fix
<!-- before --> <svg><text>hi</p></svg> <!-- after --> <svg><text>hi</text></svg>
Defensive patterns
Strategy: validation
Validate before calling
const VOID: &[&str] = &["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"];
// Heuristic stack checker: flags end tags that do not match the innermost open tag.
fn find_mismatched_end_tags(html: &str) -> Vec<String> {
let lower = html.to_ascii_lowercase();
let mut stack: Vec<String> = Vec::new();
let mut bad = Vec::new();
for (i, _) in lower.match_indices('<') {
let rest = &lower[i + 1..];
let (closing, body) = match rest.strip_prefix('/') {
Some(b) => (true, b),
None => (false, rest),
};
let name: String = body.chars().take_while(char::is_ascii_alphanumeric).collect();
if name.is_empty() { continue; }
if closing {
match stack.last() {
Some(open) if open == &name => { stack.pop(); }
_ => bad.push(format!("</{}> at byte {}", name, i)),
}
} else if !VOID.contains(&name.as_str()) {
stack.push(name);
}
}
bad
} Try / catch
use swc_html_parser::error::ErrorKind;
let mut errors = Vec::new();
let doc = swc_html_parser::parse_file_as_document(&fm, config, &mut errors)?;
for err in &errors {
if let ErrorKind::EndTagDidNotMatchCurrentOpenElement(end, current) = err.kind() {
// Foreign content was force-closed so </p> could be reprocessed as HTML
log::warn!("</{}> saw open <{}>", end, current);
}
} Prevention
- Keep open/close pairs for p and br inside the HTML (non-foreign) part of the document
- Close foreign elements explicitly before resuming HTML markup
- Render conditional closers together with their openers in templates
When it happens
Trigger: `</p>` or `</br>` inside an <svg>/<math> subtree, e.g. `<svg><text>hi</p></svg>`. Frequently the tail of a missing foreign-element boundary: after an unclosed <svg>/<math>, subsequent end tags are dispatched to foreign content until a breakout token resets the mode.
Common situations: Templates that conditionally emit the closing </svg> but always emit a trailing </p>, minified or machine-mangled markup, hand-edited SVG islands in HTML pages.
Related errors
- HTML start tag "{tag_name}" in a foreign namespace context
- Stray end tag "{tag_name}"
- Unexpected null character
- Stray doctype
- End tag seen without seeing a doctype first, expected "<!DOC
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/e61be4da8352ff4f.
Report an issue: GitHub.