swc-project/swc · warning · Error
No cell to close
Error message
No cell to close
What it means
In the "in cell" insertion mode, an end tag `caption`, `table`, `tbody`, `tfoot`, `thead`, or `tr` was seen while neither `td` nor `th` is in table scope. HTML5 defines this as a parse error ("no cell to close"); the token is ignored. It means a table-structure closer arrived when the cell it should implicitly close is already gone.
Source
Thrown at crates/swc_html_parser/src/parser/mod.rs:5590
Token::StartTag { tag_name, .. }
if matches!(
&**tag_name,
"caption"
| "col"
| "colgroup"
| "tbody"
| "td"
| "tfoot"
| "th"
| "thead"
| "tr"
) =>
{
if !self.open_elements_stack.has_in_table_scope("td")
&& !self.open_elements_stack.has_in_table_scope("th")
{
self.errors
.push(Error::new(token_and_info.span, ErrorKind::NoCellToClose));
} else {
self.close_the_cell();
self.process_token(token_and_info, None)?;
}
}
// An end tag whose tag name is one of: "body", "caption", "col", "colgroup",
// "html"
//
// Parse error. Ignore the token.
Token::EndTag { tag_name, .. }
if matches!(
&**tag_name,
"body" | "caption" | "col" | "colgroup" | "html"
) =>
{
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::StrayEndTag(tag_name.clone()),View on GitHub (pinned to 5176682b65)
Solutions
- Simplify the nesting: remove leftover `</tr>`/`</tbody>`/`</table>` closers that no longer have a matching open element.
- Regenerate the table from data with a trusted template engine instead of patching broken markup.
- Validate with the W3C/WHATWG checker; it reports every unmatched structure closer with its position.
- Treat as recoverable for third-party content: the token is ignored; log the `NoCellToClose` entry from the `errors` vec and use the corrected tree.
Example fix
<!-- before: leftover </tr> after the row was already closed --> <table><tr><td>a</td></tr></tr></table> <!-- after --> <table><tr><td>a</td></tr></table>
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check: structure closers without matching openers anywhere in the document
fn stray_structure_closers(html: &str) -> Vec<&'static str> {
["caption", "table", "tbody", "tfoot", "thead", "tr"]
.into_iter()
.filter(|t| html.matches(&format!("<{t}")).count() < html.matches(&format!("</{t}")).count())
.collect()
} Type guard
use swc_html_parser::error::{Error, ErrorKind};
fn is_no_cell_to_close(err: &Error) -> bool {
matches!(err.kind(), ErrorKind::NoCellToClose)
} Try / catch
let mut errors = Vec::new();
match parse_file_as_document(&fm, config, &mut errors) {
Ok(doc) => {
for e in errors.iter().filter(|e| matches!(e.kind(), ErrorKind::NoCellToClose)) {
// token ignored per spec; tree recovered — log with span for upstream fix
}
}
Err(fatal) => return Err(fatal.into()),
} Prevention
- Never hand-nest tables; generate them from structured data with a trusted template engine.
- Remove leftover section/row closers when deleting cells from exported tables (Excel/Word exports are repeat offenders).
- Run the WHATWG/W3C checker on machine-generated tables before ingestion.
- Monitor NoCellToClose in the errors vec as a data-quality signal for imported HTML.
When it happens
Trigger: Deeply malformed/nested tables where the open cell was already popped from table scope (e.g. by a nested `<table>` reset or duplicated section closers) before `</table>`, `</tbody>`, `</tfoot>`, `</thead>`, `</caption>`, or `</tr>` arrived — e.g. `<table><tr><td><table><tr><td>x</table></tr></table></tr></table>`-style leftover closers.
Common situations: Machine-generated tables (Excel/Word exports, report engines) with extra section/row closers; hand-nested tables where inner and outer closers get confused; sanitizer output that removed cells but kept structure closers.
Related errors
- "{tag_name}" end tag with "select" open
- "select" start tag where end tag expected
- "{tag_name}" start tag with "select" open
- End of file seen and there were open elements
- Non-space character after body
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/66cc426628af43ba.
Report an issue: GitHub.