swc-project/swc · warning · swc_html_parser::error::Error
StartTagInTable
StartTagInTable
Error message
Start tag "{tag_name}" seen in "table" What it means
Inside a table (the 'in table' insertion mode) only a narrow set of table-related tags is allowed; anything else triggers the foster-parenting path. This error is reported when the unexpected token is a start tag: `process_token_in_table_insertion_mode_anything_else` (crates/swc_html_parser/src/parser/mod.rs:6711) records the tag name, then the parser enables foster parenting and reprocesses the token so the element is inserted before/around the table, per the HTML standard.
Source
Thrown at crates/swc_html_parser/src/parser/mod.rs:6711
}
_ => {
unreachable!();
}
},
}
}
}
Ok(())
}
fn process_token_in_table_insertion_mode_anything_else(
&mut self,
token_and_info: &mut TokenAndInfo,
) -> PResult<()> {
match &token_and_info.token {
Token::StartTag { tag_name, .. } => {
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::StartTagInTable(tag_name.clone()),
));
}
Token::EndTag { tag_name, .. } => {
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::StrayEndTag(tag_name.clone()),
));
}
Token::Character { .. } => {
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::NonSpaceCharacterInTable,
));
}
_ => {
unreachable!();View on GitHub (pinned to 5176682b65)
Solutions
- Move the non-table element out of <table>, into a <td>/<th> cell or before/after the table
- If it is styling/scripting, use the allowed <style>/<script> or <template> exceptions
- Restructure legacy table layouts so only legal table children appear directly under table
- Accept the recovered (foster-parented) output but keep the diagnostic in your HTML lint report
Example fix
<!-- before --> <table><div>x</div><tr><td>cell</td></tr></table> <!-- after --> <div>x</div><table><tr><td>cell</td></tr></table>
Defensive patterns
Strategy: validation
Validate before calling
// Flag non-table elements directly under <table> (foster-parenting cases)
function assertTableChildren(tableHtml: string): void {
const inner = tableHtml.replace(/<table[^>]*>|<\/?(table|tbody|thead|tfoot|tr|td|th|caption|colgroup|col|style|script|template|form)\b[^>]*>/gi, '');
if (/<[a-zA-Z]/.test(inner)) throw new Error('non-table element inside <table>');
} Try / catch
for err in parser.take_errors() {
if matches!(err.kind, ErrorKind::StartTagInTable(_)) {
// parser recovers via foster parenting; verify placement in output
}
} Prevention
- Place layout divs and spans outside the table or inside td/th cells
- Only style/script/template/form/input[type=hidden] may sit directly in table
- Snapshot-test the normalized tree for table-heavy templates (email HTML)
When it happens
Trigger: Parsing markup such as `<table><div>x</div></table>` or `<table><span>hi</span></table>` — any start tag that is not legal in the table insertion mode (not caption/colgroup/tbody/tfoot/thead/tr/td/th/style/script/template/form/input[type=hidden]). The div/span start tag produces `StartTagInTable("div")` and the node is foster-parented outside the table.
Common situations: Wrapping layout divs inside table-based email templates; legacy table layouts with `<font>`/`<span>` between rows; CMS output injecting wrapper tags into tables; copy-pasting div-based content into table cells at the wrong nesting level.
Related errors
- NonSpaceCharacterInTable
- Start tag for "table" seen but the previous "table" is still
- No cell to close
- "{tag_name}" end tag with "select" open
- UnclosedElementsCell
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/215e282a6e17946d.
Report an issue: GitHub.