{"record":{"id":"ea90b5f54692dc0d","repo":"swc-project/swc","slug":"tag-name-end-tag-with-select-open","errorCode":null,"errorMessage":"\"{tag_name}\" end tag with \"select\" open","messagePattern":"\"(.+?)\" end tag with \"select\" open","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"crates/swc_html_parser/src/parser/mod.rs","lineNumber":5987,"sourceCode":"                    // If the stack of open elements does not have an element in table scope that is\n                    // an HTML element with the same tag name as that of the token, then ignore the\n                    // token.\n                    //\n                    // Otherwise:\n                    //\n                    // Pop elements from the stack of open elements until a select element has been\n                    // popped from the stack.\n                    //\n                    // Reset the insertion mode appropriately.\n                    //\n                    // Reprocess the token.\n                    Token::EndTag { tag_name, .. }\n                        if matches!(\n                            &**tag_name,\n                            \"caption\" | \"table\" | \"tbody\" | \"tfoot\" | \"thead\" | \"tr\" | \"td\" | \"th\"\n                        ) =>\n                    {\n                        self.errors.push(Error::new(\n                            token_and_info.span,\n                            ErrorKind::EndTagSeenWithSelectOpen(tag_name.clone()),\n                        ));\n\n                        if !self.open_elements_stack.has_in_table_scope(tag_name) {\n                            // Ignore\n                            return Ok(());\n                        }\n\n                        self.open_elements_stack\n                            .pop_until_tag_name_popped(&[\"select\"]);\n                        self.reset_insertion_mode();\n                        self.process_token(token_and_info, None)?;\n                    }\n                    // Anything else\n                    //\n                    // Process the token using the rules for the \"in select\" insertion mode.\n                    _ => {","sourceCodeStart":5969,"sourceCodeEnd":6005,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_html_parser/src/parser/mod.rs#L5969-L6005","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"<!-- before: select not closed before </td> -->\n<table><tr><td><select><option>a</option></td></tr></table>\n\n<!-- after -->\n<table><tr><td><select><option>a</option></select></td></tr></table>","handlingStrategy":"validation","validationCode":"// Pre-check: table end tags must not appear while a <select> is unclosed\nfn table_end_tag_with_select_open(html: &str) -> Option<&'static str> {\n    let lower = html.to_ascii_lowercase();\n    let mut select_depth = 0usize;\n    for (i, _) in lower.match_indices('<') {\n        let rest = &lower[i..];\n        if rest.starts_with(\"<select\") {\n            select_depth += 1;\n        } else if rest.starts_with(\"</select\") {\n            select_depth = select_depth.saturating_sub(1);\n        } else if select_depth > 0\n            && [\"</caption\", \"</table\", \"</tbody\", \"</tfoot\", \"</thead\", \"</tr\", \"</td\", \"</th\"]\n                .iter()\n                .any(|t| rest.starts_with(t))\n        {\n            return Some(&lower[i + 2..].split([' ', '>', '/']).next().unwrap());\n        }\n    }\n    None\n}","typeGuard":"use swc_html_parser::error::{Error, ErrorKind};\n\nfn is_table_end_with_select_open(err: &Error) -> bool {\n    matches!(err.kind(), ErrorKind::EndTagSeenWithSelectOpen(_))\n}","tryCatchPattern":"let mut errors = Vec::new();\nlet doc = parse_file_as_document(&fm, config, &mut errors)?;\nfor e in errors.iter().filter(|e| matches!(e.kind(), ErrorKind::EndTagSeenWithSelectOpen(_))) {\n    // select was popped (or tag ignored); tree recovered — report missing </select> upstream\n}","preventionTips":["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)."],"tags":["html","html-parser","select","table","stray-end-tag","parse-error","swc"],"backgroundTag":"table-tags-inside-select","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}