{"record":{"id":"ad080844830ad768","repo":"swc-project/swc","slug":"start-tag-tag-name-seen-in-table","errorCode":null,"errorMessage":"Start tag \"{tag_name}\" seen in \"table\"","messagePattern":"Start tag \"(.+?)\" seen in \"table\"","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"crates/swc_html_parser/src/parser/mod.rs","lineNumber":4775,"sourceCode":"                        let is_self_closing = *is_self_closing;\n                        let input_type =\n                            attributes.iter().find(|attribute| attribute.name == \"type\");\n                        let is_hidden = match &input_type {\n                            Some(input_type) => match &input_type.value {\n                                Some(value) if value.as_ref().eq_ignore_ascii_case(\"hidden\") => {\n                                    true\n                                }\n                                _ => false,\n                            },\n                            _ => false,\n                        };\n\n                        if input_type.is_none() || !is_hidden {\n                            self.process_token_in_table_insertion_mode_anything_else(\n                                token_and_info,\n                            )?;\n                        } else {\n                            self.errors.push(Error::new(\n                                token_and_info.span,\n                                ErrorKind::StartTagInTable(tag_name.clone()),\n                            ));\n\n                            self.insert_html_element(token_and_info)?;\n                            self.open_elements_stack.pop();\n\n                            if is_self_closing {\n                                token_and_info.acknowledged = true;\n                            }\n                        }\n                    }\n                    // A start tag whose tag name is \"form\"\n                    //\n                    // Parse error.\n                    //\n                    // If there is a template element on the stack of open elements, or if the form\n                    // element pointer is not null, ignore the token.","sourceCodeStart":4757,"sourceCodeEnd":4793,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_html_parser/src/parser/mod.rs#L4757-L4793","documentation":"A start tag `input` with `type=hidden` was seen in the \"in table\" insertion mode (parser/mod.rs:4755-4790). Hidden inputs are the only inputs allowed in table content (a spec carve-out so forms can embed data in tables); it is still a parse error. The parser records `StartTagInTable(\"input\")`, inserts the element, and immediately pops it (input is void). Non-hidden inputs take the foster-parenting path instead and produce different errors.","triggerScenarios":"`<table><input type=\"hidden\" name=\"row_id\" value=\"7\"><tr>...` — an `<input type=hidden>` placed directly inside `<table>`, `<tbody>`, or `<tr>` rather than inside a `<td>`/`<th>` cell. Any other input type (or missing type) does not hit this arm.","commonSituations":"Server-rendered grids that attach per-table form data (pagination tokens, CSRF fields) directly under `<table>`; ASP.NET WebForms-era patterns; auto-injected hidden fields from frameworks that assume body context.","solutions":["Move the hidden input into a cell: `<td><input type=\"hidden\" ...></td>` (or outside the table entirely)","Emit framework-injected hidden fields before the `<table>` opens","Keep the placement only if you deliberately rely on the spec carve-out — the tree is still correct — but expect the parse-error warning","Filter `StartTagInTable` from take_errors() when ingesting third-party grid HTML you cannot change"],"exampleFix":"<!-- before -->\n<table><input type=\"hidden\" name=\"id\" value=\"7\"><tr><td>x</td></tr></table>\n\n<!-- after -->\n<input type=\"hidden\" name=\"id\" value=\"7\">\n<table><tr><td>x</td></tr></table>","handlingStrategy":"validation","validationCode":"// Reject <input type=hidden> (or any input) placed directly under table/tbody/tr\nfn input_directly_in_table(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 matches!(n.as_str(), \"table\"|\"tbody\"|\"thead\"|\"tfoot\"|\"tr\") => stack.push(n.clone()),\n            End(ref n) if matches!(n.as_str(), \"table\"|\"tbody\"|\"thead\"|\"tfoot\"|\"tr\") => {\n                while let Some(t) = stack.pop() { if t == *n { break; } }\n            }\n            Start(ref n) if n == \"input\" => {\n                if stack.last().is_some() { return true; } // no td/th between input and table tags\n            }\n            _ => {}\n        }\n    }\n    false\n}","typeGuard":"fn is_hidden_input_in_table(e: &Error) -> bool {\n    matches!(e.kind, ErrorKind::StartTagInTable(ref t) if &**t == \"input\")\n}","tryCatchPattern":"let doc = parser.parse_document()?;\nif parser.take_errors().into_iter().any(is_hidden_input_in_table) {\n    // tree is still correct (spec carve-out for hidden inputs) — report only\n    log::warn!(\"<input type=hidden> directly in table markup\");\n}","preventionTips":["Emit framework hidden fields (CSRF, pagination) before the table opens","Or place them inside a td/th cell","When ingesting third-party grids, whitelist StartTagInTable('input') as accepted noise"],"tags":["html","parser","table","input","hidden-field","in-table"],"backgroundTag":"invalid-tag-in-table","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"}