dompdf/dompdf · error · Exception
Parent table not found for table cell
Error message
Parent table not found for table cell
What it means
This exception is thrown by the TableCell renderer when it cannot find a Table ancestor for the table-cell frame it is asked to render. During layout, dompdf walks the frame tree upward via Table::find_parent_table() (src/FrameDecorator/Table.php:158) looking for a frame where is_table() is true; if the walk reaches the top without finding one, it returns null and TableCell::render() aborts with this message. It almost always indicates a broken frame tree, which in practice means invalid HTML: a td/th element that never ended up inside a proper table structure after parsing/tree-building. This is an internal consistency error, not a user-configurable condition.
Source
Thrown at src/Renderer/TableCell.php:37
{
/**
* @param Frame $frame
*/
function render(Frame $frame)
{
$style = $frame->get_style();
$node = $frame->get_node();
if (trim($node->nodeValue) === "" && $style->empty_cells === "hide") {
return;
}
$this->_set_opacity($frame->get_opacity($style->opacity));
$border_box = $frame->get_border_box();
$table = Table::find_parent_table($frame);
if ($table === null) {
throw new Exception("Parent table not found for table cell");
}
if ($table->get_style()->border_collapse !== "collapse") {
$this->_render_background($frame, $border_box);
$this->_render_border($frame, $border_box);
$this->_render_outline($frame, $border_box);
} else {
// The collapsed case is slightly complicated...
$cells = $table->get_cellmap()->get_spanned_cells($frame);
if (is_null($cells)) {
return;
}
// Render the background to the padding box, as the cells are
// rendered individually one after another, and we don't want the
// background to overlap an adjacent borderView on GitHub (pinned to b14267808b)
Solutions
- Fix the source HTML so every <td>/<th> sits inside a well-formed <table> ... <tr> ... structure, then re-render.
- Sanitize/repair the HTML before loadHtml(): parse it with DOMDocument, find td/th nodes with no table ancestor, and either wrap them in a table or drop them.
- Upgrade dompdf to the latest release — several historical bugs where valid nested tables produced orphaned cell frames (triggering this exact exception) have been fixed in the table layout code.
- If you build or mutate frames yourself, ensure any TableCell frame you insert has a Table frame as an ancestor before rendering.
- Wrap the render() call in a try/catch for this case and fall back to an error page or HTML-escaped output so one bad document does not kill a batch job.
Example fix
// before $html = '<td>Price</td><td>12.00</td>'; // bare cells, no table wrapper $dompdf->loadHtml($html); $dompdf->render(); // throws "Parent table not found for table cell" // after $html = '<table><tr><td>Price</td><td>12.00</td></tr></table>'; $dompdf->loadHtml($html); $dompdf->render();
Defensive patterns
Strategy: validation
Validate before calling
// Before loadHtml(): ensure every cell is inside a table
$doc = new DOMDocument();
libxml_use_internal_errors(true);
$doc->loadHTML($html, LIBXML_NOWARNING | LIBXML_NOERROR);
$xpath = new DOMXPath($doc);
$badCells = $xpath->query('//td[not(ancestor::table)] | //th[not(ancestor::table)]');
if ($badCells->length > 0) {
// wrap strays in a table, drop them, or reject the input
$html = stripOrWrapStrayCells($doc, $badCells);
}
$dompdf->loadHtml($html); Try / catch
try {
$dompdf->render();
} catch (\Exception $e) {
if (str_contains($e->getMessage(), 'Parent table not found for table cell')) {
// log the offending HTML, sanitize it, or return a safe fallback document
logger()->warning('dompdf: stray table cell in input HTML', ['html' => $html]);
$dompdf->loadHtml(htmlspecialchars($html));
$dompdf->render();
} else {
throw $e;
}
} Prevention
- Always emit tables through a templating layer that guarantees the <table>/<tr> wrapper instead of concatenating raw <td> fragments.
- Run user-supplied HTML through an HTML sanitizer/repairer (DOMDocument round-trip, tidy, or htmlpurifier) before passing it to loadHtml().
- Keep dompdf up to date — several orphaned-cell frame-tree bugs that trigger this exception were fixed in later releases.
- In automated/batch pipelines, wrap render() in a catch-all that records the source HTML so bad documents can be reproduced and fixed.
When it happens
Trigger: Rendering HTML that contains a <td> or <th> not nested inside a <table><tr> chain (e.g. a bare <td> directly under <body> or a <div>); malformed table markup such as a <tr> or <table> closed early so libxml's tree builder reparents the cell outside the table subtree; HTML from WYSIWYG editors or templating that emits fragments like '<td>...</td>' without the surrounding table tags; or custom code that manipulates/injects cell frames into the dompdf FrameTree without a Table parent.
Common situations: Server-side PDF generation from user-submitted or CMS-sourced HTML that contains copy-pasted table fragments missing the outer <table> tag; HTML truncated by a max-length column or a regex-based sanitizer that strips the <table> wrapper but leaves <td>; older dompdf versions where certain nested-table and colspan/rowspan combinations (e.g. cells inside nested tables split across pages) could leave orphaned cell frames after table/tree fixups; feeding an HTML fragment rather than a full document to Dompdf::loadHtml() and bypassing normal tree building.
Related errors
- Reference child is not a child of this node.
- Requested HTML document contains no data.
- Parent table not found for table row
- Parent table not found for table cell
- Parent table not found for table row
AI-assisted analysis of dompdf/dompdf@b14267808b (2026-08-21).
Data as JSON: /api/errors/4322ba9f63e5a006.
Report an issue: GitHub.