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

  1. Move the non-table element out of <table>, into a <td>/<th> cell or before/after the table
  2. If it is styling/scripting, use the allowed <style>/<script> or <template> exceptions
  3. Restructure legacy table layouts so only legal table children appear directly under table
  4. 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

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


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/215e282a6e17946d. Report an issue: GitHub.