swc-project/swc · warning · Error
Start tag "{tag_name}" seen but an element of the same type
Error message
Start tag "{tag_name}" seen but an element of the same type was already open What it means
A start tag `a` was found while the list of active formatting elements already contains an `a` element between the end of the list and the last marker (parser/mod.rs:3494-3515). HTML forbids nested anchors, so the parser records `SomethingSeenWhenSomethingOpen("a")`, runs the adoption agency algorithm, and removes the old anchor from the active formatting list and the open elements stack before inserting the new one.
Source
Thrown at crates/swc_html_parser/src/parser/mod.rs:3513
let mut node = None;
for element in self.active_formatting_elements.items.iter().rev() {
match element {
ActiveFormattingElement::Marker => {
break;
}
ActiveFormattingElement::Element(item, _) => {
if is_html_element!(item, "a") {
node = Some(item);
break;
}
}
}
}
if let Some(element) = node {
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::SomethingSeenWhenSomethingOpen(tag_name.clone()),
));
let remove = element.clone();
self.run_the_adoption_agency_algorithm(token_and_info, false)?;
self.active_formatting_elements.remove(&remove);
self.open_elements_stack.remove(&remove);
}
}
self.reconstruct_active_formatting_elements()?;
let element = self.insert_html_element(token_and_info)?;
self.active_formatting_elements
.push(ActiveFormattingElement::Element(View on GitHub (pinned to 5176682b65)
Solutions
- Close the previous anchor before opening the next: `<a>first</a> <a>second</a>`
- Fix the template loop/generator so each emitted anchor is fully closed
- Sanitize input with a whitelist-based sanitizer that auto-balances tags before parsing
- Check `take_errors()` for `SomethingSeenWhenSomethingOpen` and reject/repair nested-link input
Example fix
<!-- before --> <a href="/a">first <a href="/b">second</a></a> <!-- after --> <a href="/a">first</a> <a href="/b">second</a>
Defensive patterns
Strategy: validation
Validate before calling
// Detect nested anchors before parsing
fn has_nested_anchor(src: &str) -> bool {
let mut a_open = false;
for tag in html_tag_tokens(src) {
match tag {
Start(ref n) if n == "a" => { if a_open { return true; } a_open = true; }
End(ref n) if n == "a" => a_open = false,
_ => {}
}
}
false
} Type guard
fn is_nested_anchor_error(e: &Error) -> bool {
matches!(e.kind, ErrorKind::SomethingSeenWhenSomethingOpen(ref t) if &**t == "a")
} Try / catch
let doc = parser.parse_document()?;
let nested = parser.take_errors().into_iter().any(is_nested_anchor_error);
if nested {
// adoption agency already flattened the anchors; decide whether to reject input
return Err(ContentRejected::NestedAnchors);
} Prevention
- Never concatenate link partials without closing the previous anchor
- Run sanitize-html / DOMPurify with balanced-tag enforcement on user HTML
- Unit-test rich-text renderers for the 'link inside link' case
When it happens
Trigger: Input like `<a href="/1">first <a href="/2">second</a></a>` — the second `<a>` start tag with an unclosed `<a>` still active. Also happens when templating loops concatenate link partials without closing the previous anchor.
Common situations: CMS rich-text editors that allow nested links, string concatenation of link fragments in server templates (`"<a>" + user1 + "<a>" + user2`), and scraped/legacy pages. Browsers silently unwrap the nesting; this error tells you the tree will be reshaped by the adoption agency algorithm.
Related errors
- HTML start tag "{tag_name}" in a foreign namespace context
- End tag "{end_tag_name}" did not match the name of the curre
- UnclosedElements
- Start tag for "table" seen but the previous "table" is still
- failed to parse input as document fragment
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/2de742aca7e7857a.
Report an issue: GitHub.