swc-project/swc · warning · Error
SomethingSeenWhenSomethingOpen
SomethingSeenWhenSomethingOpen
Error message
Start tag "{tag_name}" seen but an element of the same type was already open What it means
The in-head insertion mode (crates/swc_html_parser/src/parser/mod.rs:1955) received a start tag named head while the head element is already the open element. The spec's message for this arm maps to SomethingSeenWhenSomethingOpen — 'start tag seen but an element of the same type was already open'. The token is ignored; the existing head continues.
Source
Thrown at crates/swc_html_parser/src/parser/mod.rs:1955
}
let popped = self
.open_elements_stack
.pop_until_tag_name_popped(&["template"]);
self.update_end_tag_span(popped.as_ref(), token_and_info.span);
self.active_formatting_elements.clear_to_last_marker();
self.template_insertion_mode_stack.pop();
self.reset_insertion_mode();
}
}
// A start tag whose tag name is "head"
//
// Any other end tag
//
// Parse error. Ignore the token.
Token::StartTag { tag_name, .. } if tag_name == "head" => {
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::SomethingSeenWhenSomethingOpen(tag_name.clone()),
));
}
Token::EndTag { tag_name, .. } => {
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::StrayEndTag(tag_name.clone()),
));
}
// Anything else
//
// Pop the current node (which will be the head element) off the stack of open
// elements.
//
// Switch the insertion mode to "after head".
//
// Reprocess the token.View on GitHub (pinned to 5176682b65)
Solutions
- Merge the two head sections into one
- Make the layout render exactly one <head> wrapper around all metadata
- Filter ErrorKind::SomethingSeenWhenSomethingOpen(tag) with tag == "head" if duplicates are benign
Example fix
<!-- before -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<head>
<title>t</title>
</head>
</html>
<!-- after -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>t</title>
</head>
</html> Defensive patterns
Strategy: validation
Validate before calling
fn head_start_tag_count(html: &str) -> usize {
let lower = html.to_ascii_lowercase();
lower
.match_indices("<head")
.filter(|(i, _)| {
// exclude <header ...>
lower[*i + 5..].starts_with(|c: char| !(c.is_ascii_alphanumeric() || c == '-'))
})
.count()
} 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::SomethingSeenWhenSomethingOpen(tag) = err.kind() {
if tag == "head" {
// Second <head> ignored; its attributes did NOT merge.
log::warn!("duplicate <head> start tag ignored");
}
}
} Prevention
- Only the page shell template may open <head>; partials contribute metadata, not wrappers
- Guard against double-rendering head boilerplate in plugin pipelines
- Note: the ignored duplicate's attributes are dropped — set lang/class on the first <head>
When it happens
Trigger: A second `<head>` start tag while still inside head: `<!DOCTYPE html><html><head><meta charset="utf-8"><head><title>t</title>`. Comments/metadata before it do not close head, so the duplicate lands in this arm.
Common situations: Two head partials concatenated by the layout system, boilerplate injected twice by CMS plugins, refactors that moved head content without removing the old wrapper tag.
Related errors
- StrayDoctype
- StrayEndTag
- failed to parse input as document fragment
- failed to parse input as document
- failed to parse input as document fragment
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/c5e0dfd4ed8f7059.
Report an issue: GitHub.