{"record":{"id":"814fd32f66628307","repo":"swc-project/swc","slug":"start-tag-for-table-seen-but-the-previous-table","errorCode":null,"errorMessage":"Start tag for \"table\" seen but the previous \"table\" is still open","messagePattern":"Start tag for \"table\" seen but the previous \"table\" is still open","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"crates/swc_html_parser/src/parser/mod.rs","lineNumber":4656,"sourceCode":"                        self.process_token(token_and_info, None)?;\n                    }\n                    // A start tag whose tag name is \"table\"\n                    //\n                    // Parse error.\n                    //\n                    // If the stack of open elements does not have a table element in table scope,\n                    // ignore the token.\n                    //\n                    // Otherwise:\n                    //\n                    // Pop elements from this stack until a table element has been popped from the\n                    // stack.\n                    //\n                    // Reset the insertion mode appropriately.\n                    //\n                    // Reprocess the token.\n                    Token::StartTag { tag_name, .. } if tag_name == \"table\" => {\n                        self.errors.push(Error::new(\n                            token_and_info.span,\n                            ErrorKind::TableSeenWhileTableOpen,\n                        ));\n\n                        if !self.open_elements_stack.has_in_table_scope(\"table\") {\n                            // Ignore\n\n                            return Ok(());\n                        }\n\n                        self.open_elements_stack\n                            .pop_until_tag_name_popped(&[\"table\"]);\n                        self.reset_insertion_mode();\n                        self.process_token(token_and_info, None)?;\n                    }\n                    // An end tag whose tag name is \"table\"\n                    //\n                    // If the stack of open elements does not have a table element in table scope,","sourceCodeStart":4638,"sourceCodeEnd":4674,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_html_parser/src/parser/mod.rs#L4638-L4674","documentation":"A start tag `table` was seen while already in the \"in table\" insertion mode — i.e. a table is already open (parser/mod.rs:4646-4665). Nested `<table>` elements are not allowed this way; the parser records `TableSeenWhileTableOpen`, then pops the open table (if it is in table scope), resets the insertion mode, and reprocesses the token so the new table is parsed at the right level.","triggerScenarios":"`<table><table><tr>...` — a second `<table>` start tag before the first `</table>`. Also string-built markup where a table-generating helper is called inside another table without closing it, or a missing `</table>` earlier in the source.","commonSituations":"Layout-table legacy code where helpers nest tables; report generators that emit a new table per row; a forgotten `</table>` makes every subsequent table appear nested, producing cascades of this error.","solutions":["Close the previous table before starting a new one (`</table>` then `<table>`)","If you actually want a nested table, put it inside a `<td>`/`<th>` cell","Audit table-generating helpers for missing close tags — one omission cascades into many errors","Use the error span to find where the previous table was opened"],"exampleFix":"<!-- before -->\n<table><tr><td>1</td></tr><table><tr><td>2</td></tr></table></table>\n\n<!-- after -->\n<table><tr><td>1</td></tr></table>\n<table><tr><td>2</td></tr></table>","handlingStrategy":"validation","validationCode":"// Flag a <table> start while another table is still open (and not inside a cell)\nfn nested_table_start(src: &str) -> bool {\n    let mut stack: Vec<String> = Vec::new();\n    for tag in html_tag_tokens(src) {\n        match tag {\n            Start(ref n) if n == \"table\" => {\n                if stack.iter().any(|s| s == \"table\") && !stack.iter().any(|s| matches!(s.as_str(), \"td\"|\"th\")) {\n                    return true;\n                }\n                stack.push(n.clone());\n            }\n            Start(ref n) if !is_void(n) => stack.push(n.clone()),\n            End(ref n) => { while let Some(t) = stack.pop() { if t == *n { break; } } }\n            _ => {}\n        }\n    }\n    false\n}","typeGuard":"fn is_table_while_table_open(e: &Error) -> bool {\n    matches!(e.kind, ErrorKind::TableSeenWhileTableOpen)\n}","tryCatchPattern":"let doc = parser.parse_document()?;\nif parser.take_errors().into_iter().any(is_table_while_table_open) {\n    // earlier table was force-closed; check for a missing </table> upstream\n    log::warn!(\"nested <table> start; prior table force-closed\");\n}","preventionTips":["Close each table before opening the next; nest tables only inside td/th","Audit table-generating helpers for missing close tags — one omission cascades","Use the error span to locate the still-open table"],"tags":["html","parser","table","nesting","in-table"],"backgroundTag":"nested-table-tags","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"}