swc-project/swc · warning · swc_html_parser::error::Error
HTML start tag "{tag_name}" in a foreign namespace context
Error message
HTML start tag "{tag_name}" in a foreign namespace context What it means
A start tag from the spec's breakout list (b, big, blockquote, body, br, center, code, dd, div, dl, dt, em, embed, h1-h6, head, hr, i, img, li, listing, menu, meta, nobr, ol, p, pre, ruby, s, small, span, strong, strike, sub, sup, table, tt, u, ul, var) was seen while the adjusted current node was in a foreign namespace (crates/swc_html_parser/src/parser/mod.rs:781). The parser records HtmlStartTagInForeignContext, calls pop_until_in_foreign() — force-closing the entire SVG/MathML subtree — and reprocesses the tag with normal HTML rules.
Source
Thrown at crates/swc_html_parser/src/parser/mod.rs:781
| "ol"
| "p"
| "pre"
| "ruby"
| "s"
| "small"
| "span"
| "strong"
| "strike"
| "sub"
| "sup"
| "table"
| "tt"
| "u"
| "ul"
| "var"
) =>
{
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::StartTag {
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()),View on GitHub (pinned to 5176682b65)
Solutions
- Close the <svg>/<math> element before any HTML layout tag; balance the foreign element's open/close pair in the template
- Use <svg><foreignObject> when you genuinely need HTML flow content inside SVG (integration points keep HTML rules active there)
- Fix the missing </svg> or </math> that swallows the following HTML
- Filter ErrorKind::HtmlStartTagInForeignContext(_) if you accept the force-close recovery
Example fix
<!-- before: <p> breaks out of the svg subtree --> <svg><p>Styled text</p></svg> <!-- after: keep them separate --> <svg></svg> <p>Styled text</p> <!-- or embed HTML inside SVG properly: --> <svg><foreignObject width="200" height="50"><p>Styled text</p></foreignObject></svg>
Defensive patterns
Strategy: validation
Validate before calling
const BREAKOUT: &[&str] = &["b","big","blockquote","body","br","center","code","dd","div","dl","dt","em","embed","h1","h2","h3","h4","h5","h6","head","hr","i","img","li","listing","menu","meta","nobr","ol","p","pre","ruby","s","small","span","strong","strike","sub","sup","table","tt","u","ul","var"];
fn html_breakout_in_foreign(html: &str) -> Option<usize> {
let lower = html.to_ascii_lowercase();
for root in ["<svg", "<math"] {
let close = format!("</{}", &root[1..]);
let mut from = 0;
while let Some(rel) = lower[from..].find(root) {
let start = from + rel;
let end = lower[start..].find(&close).map(|i| start + i).unwrap_or(lower.len());
for (i, _) in lower[start..end].match_indices('<') {
let rest = &lower[start + i + 1..];
let rest = rest.strip_prefix('/').unwrap_or(rest);
let name: String = rest.chars().take_while(char::is_ascii_alphanumeric).collect();
if BREAKOUT.contains(&name.as_str()) {
return Some(start + i);
}
}
from = end + close.len();
}
}
None
} 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::HtmlStartTagInForeignContext(tag) = err.kind() {
// The svg/math subtree was force-closed at this tag; check if that
// truncated content you cared about.
log::warn!("html tag <{tag}> closed foreign content");
}
} Prevention
- Never put HTML layout tags directly inside <svg>/<math>; close the foreign element first
- Use <foreignObject> for HTML-in-SVG (it is an HTML integration point)
- Lint templates for unbalanced <svg>/<math> open/close pairs
When it happens
Trigger: Input like `<svg><p>hi</p></svg>`, `<math><div>x</div></math>`, or any HTML layout/typography tag opened between <svg>/<math> and its matching close tag. Very frequent when a closing </svg> or </math> is missing, so all subsequent page HTML is dispatched as foreign content until a breakout tag appears.
Common situations: Authors wrapping page layout in SVG by mistake, WYSIWYG editors injecting <br>/<p> inside SVG islands, template partials that conditionally drop the </svg>, appended HTML after an unclosed <math> formula.
Related errors
- Stray doctype
- End tag "{end_tag_name}" did not match the name of the curre
- Unexpected null character
- Stray end tag "{tag_name}"
- UnclosedElements
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/176bd65ee0c80410.
Report an issue: GitHub.