{"record":{"id":"819d4cd7a3e63318","repo":"swc-project/swc","slug":"stray-start-tag-tag-name","errorCode":null,"errorMessage":"Stray start tag \"{tag_name}\"","messagePattern":"Stray start tag \"(.+?)\"","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"crates/swc_html_parser/src/parser/mod.rs","lineNumber":4217,"sourceCode":"                    //\n                    // Parse error. Ignore the token.\n                    Token::StartTag { tag_name, .. }\n                        if matches!(\n                            &**tag_name,\n                            \"caption\"\n                                | \"col\"\n                                | \"colgroup\"\n                                | \"frame\"\n                                | \"head\"\n                                | \"tbody\"\n                                | \"td\"\n                                | \"tfoot\"\n                                | \"th\"\n                                | \"thead\"\n                                | \"tr\"\n                        ) =>\n                    {\n                        self.errors.push(Error::new(\n                            token_and_info.span,\n                            ErrorKind::StrayStartTag(tag_name.clone()),\n                        ));\n                    }\n                    // Any other start tag\n                    //\n                    // Reconstruct the active formatting elements, if any.\n                    //\n                    // Insert an HTML element for the token.\n                    Token::StartTag {\n                        is_self_closing,\n                        tag_name,\n                        ..\n                    } => {\n                        self.reconstruct_active_formatting_elements()?;\n                        self.insert_html_element(token_and_info)?;\n                        maybe_allow_self_closing!(is_self_closing, tag_name);\n                    }","sourceCodeStart":4199,"sourceCodeEnd":4235,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_html_parser/src/parser/mod.rs#L4199-L4235","documentation":"While in the \"in body\" insertion mode, a start tag for `caption`, `col`, `colgroup`, `frame`, `head`, `tbody`, `td`, `tfoot`, `th`, `thead`, or `tr` arrived (parser/mod.rs:4197-4221). These tags only make sense inside a table/frameset context; in body content the spec says: parse error, ignore the token completely — no element is created and the content is dropped from the tree.","triggerScenarios":"`<div><td>cell</td></div>`, `<body><tr><td>x`, `<span><thead>` — any table-structure tag encountered with no table context. Also `<frame>` after content when the document isn't a frameset.","commonSituations":"Table rows copied into non-table containers; templates where a row partial is reused outside its table; legacy frameset pages parsed as normal documents; email HTML built by string concat that drops the `<table>` wrapper.","solutions":["Wrap the markup in a proper `<table>` (with `<tbody>`/`<tr>` as needed) so the tags land in table context","If copying row/cell partials, always include the table scaffolding around them","Replace `<frame>`-based layouts (obsolete) with iframes or CSS layout","Note the token is IGNORED — unlike most parse errors the content disappears from the tree, so fix the input rather than tolerating it"],"exampleFix":"<!-- before -->\n<div><tr><td>cell</td></tr></div>\n\n<!-- after -->\n<div><table><tbody><tr><td>cell</td></tr></tbody></table></div>","handlingStrategy":"validation","validationCode":"// Detect table-structure tags that are not inside a <table> ancestor\nfn table_tags_outside_table(src: &str) -> bool {\n    let mut table = 0i32;\n    for tag in html_tag_tokens(src) {\n        match tag {\n            Start(ref n) if n == \"table\" => table += 1,\n            End(ref n) if n == \"table\" => table = table.saturating_sub(1),\n            Start(ref n) if matches!(n.as_str(), \"caption\"|\"col\"|\"colgroup\"|\"frame\"|\"head\"|\"tbody\"|\"td\"|\"tfoot\"|\"th\"|\"thead\"|\"tr\") && table == 0 => return true,\n            _ => {}\n        }\n    }\n    false\n}","typeGuard":"fn is_stray_table_start_tag(e: &Error) -> bool {\n    matches!(\n        e.kind,\n        ErrorKind::StrayStartTag(ref t)\n            if matches!(&**t, \"caption\"|\"col\"|\"colgroup\"|\"frame\"|\"head\"|\"tbody\"|\"td\"|\"tfoot\"|\"th\"|\"thead\"|\"tr\")\n    )\n}","tryCatchPattern":"let doc = parser.parse_document()?;\nif parser.take_errors().into_iter().any(is_stray_table_start_tag) {\n    // CRITICAL: the token was IGNORED — content is missing from the tree; reject input\n    return Err(ContentRejected::TableMarkupOutsideTable);\n}","preventionTips":["Never reuse row/cell partials outside a <table> wrapper","Remember this family drops content (token ignored), unlike most recoveries","CI-validate built HTML for td/tr/tbody appearing without a table ancestor"],"tags":["html","parser","table","start-tag","in-body","ignored-token"],"backgroundTag":"table-tag-outside-table-context","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"}