swc-project/swc · warning · Error
"{tag_name}" end tag with "select" open
Error message
"{tag_name}" end tag with "select" open What it means
In the "in select in table" mode, an end tag `caption`, `table`, `tbody`, `tfoot`, `thead`, `tr`, `td`, or `th` was seen while a select is open. HTML5 defines this as a parse error; if the named element is not in table scope the token is ignored, otherwise the parser pops the select, resets the insertion mode, and reprocesses. Note the error is reported before the scope check, so it fires in both paths.
Source
Thrown at crates/swc_html_parser/src/parser/mod.rs:5987
// If the stack of open elements does not have an element in table scope that is
// an HTML element with the same tag name as that of the token, then ignore the
// token.
//
// Otherwise:
//
// Pop elements from the stack of open elements until a select element has been
// popped from the stack.
//
// Reset the insertion mode appropriately.
//
// Reprocess the token.
Token::EndTag { tag_name, .. }
if matches!(
&**tag_name,
"caption" | "table" | "tbody" | "tfoot" | "thead" | "tr" | "td" | "th"
) =>
{
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::EndTagSeenWithSelectOpen(tag_name.clone()),
));
if !self.open_elements_stack.has_in_table_scope(tag_name) {
// Ignore
return Ok(());
}
self.open_elements_stack
.pop_until_tag_name_popped(&["select"]);
self.reset_insertion_mode();
self.process_token(token_and_info, None)?;
}
// Anything else
//
// Process the token using the rules for the "in select" insertion mode.
_ => {View on GitHub (pinned to 5176682b65)
Solutions
- Add the missing `</select>` before `</td>`/`</tr>`/`</table>`.
- Emit select widgets as complete atomic blocks (`<select>…</select>`) inside cells.
- Pre-validate: flag table end tags that appear while a `<select` is unclosed.
- Recovery pops the select and reprocesses the closer; log `EndTagSeenWithSelectOpen` from the `errors` vec.
Example fix
<!-- before: select not closed before </td> --> <table><tr><td><select><option>a</option></td></tr></table> <!-- after --> <table><tr><td><select><option>a</option></select></td></tr></table>
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check: table end tags must not appear while a <select> is unclosed
fn table_end_tag_with_select_open(html: &str) -> Option<&'static str> {
let lower = html.to_ascii_lowercase();
let mut select_depth = 0usize;
for (i, _) in lower.match_indices('<') {
let rest = &lower[i..];
if rest.starts_with("<select") {
select_depth += 1;
} else if rest.starts_with("</select") {
select_depth = select_depth.saturating_sub(1);
} else if select_depth > 0
&& ["</caption", "</table", "</tbody", "</tfoot", "</thead", "</tr", "</td", "</th"]
.iter()
.any(|t| rest.starts_with(t))
{
return Some(&lower[i + 2..].split([' ', '>', '/']).next().unwrap());
}
}
None
} Type guard
use swc_html_parser::error::{Error, ErrorKind};
fn is_table_end_with_select_open(err: &Error) -> bool {
matches!(err.kind(), ErrorKind::EndTagSeenWithSelectOpen(_))
} Try / catch
let mut errors = Vec::new();
let doc = parse_file_as_document(&fm, config, &mut errors)?;
for e in errors.iter().filter(|e| matches!(e.kind(), ErrorKind::EndTagSeenWithSelectOpen(_))) {
// select was popped (or tag ignored); tree recovered — report missing </select> upstream
} Prevention
- Close every select before closing its cell: <td><select>…</select></td>.
- Make editor auto-closing and template conditionals emit </select> reliably.
- Assert select depth is zero at each </td>/</tr> in component tests.
- Remember the error fires even when the end tag is then ignored (scope check comes after).
When it happens
Trigger: Closing a cell/row/table while a select in that cell is still open, e.g. `<table><tr><td><select><option>a</option></td></tr></table>` — `</td>` arrives with the select unclosed.
Common situations: Templates that forget `</select>` before closing the cell; editor auto-closing that drops the select closer; component output where the select's end tag is omitted by a broken conditional.
Related errors
- No cell to close
- "select" start tag where end tag expected
- "{tag_name}" start tag with "select" open
- End of file seen and there were open elements
- Non-space character after body
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/ea90b5f54692dc0d.
Report an issue: GitHub.