{"record":{"id":"b081e75c58b61543","repo":"PHPOffice/PHPWord","slug":"can-not-find-the-start-position-of-the-table","errorCode":null,"errorMessage":"Can not find the start position of the table.","messagePattern":"Can not find the start position of the table\\.","errorType":"exception","errorClass":"PhpOffice\\PhpWord\\Exception\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpWord/TemplateProcessor.php","lineNumber":1224,"sourceCode":"     * Find the start position of the nearest table before $offset.\n     */\n    private function findTableStart(int $offset): int\n    {\n        $rowStart = strrpos(\n            $this->tempDocumentMainPart,\n            '<w:tbl ',\n            ((strlen($this->tempDocumentMainPart) - $offset) * -1)\n        );\n\n        if (!$rowStart) {\n            $rowStart = strrpos(\n                $this->tempDocumentMainPart,\n                '<w:tbl>',\n                ((strlen($this->tempDocumentMainPart) - $offset) * -1)\n            );\n        }\n        if (!$rowStart) {\n            throw new Exception('Can not find the start position of the table.');\n        }\n\n        return $rowStart;\n    }\n\n    /**\n     * Find the end position of the nearest table row after $offset.\n     */\n    private function findTableEnd(int $offset): int\n    {\n        return strpos($this->tempDocumentMainPart, '</w:tbl>', $offset) + 7;\n    }\n\n    /**\n     * Find the start position of the nearest table row before $offset.\n     *\n     * @param int $offset\n     *","sourceCodeStart":1206,"sourceCodeEnd":1242,"githubUrl":"https://github.com/PHPOffice/PHPWord/blob/aef95c04151b5633cc505f672ddd6a71da900ee1/src/PhpWord/TemplateProcessor.php#L1206-L1242","documentation":"findTableStart() walks backwards from the placeholder position in the main document XML looking for the opening '<w:tbl>' tag. If no opening table tag exists before the offset it throws, because deleteRow requires the placeholder to sit inside a table. The document structure is not what the caller assumed.","triggerScenarios":"deleteRow() called with a placeholder that is not inside a <w:tbl> element — e.g. the variable is in a normal paragraph, in a header/footer rather than the main part, or the surrounding table markup was altered by another tool.","commonSituations":"Using deleteRow on a variable that lives outside any table; template regenerated by another tool that alters table XML; placeholder placed in headers/footers instead of the document body.","solutions":["Confirm the placeholder is inside a table body row (<w:tr>) in document.xml.","Use cloneRow/deleteRow only for table-bound variables; use setValue() for paragraph variables.","Re-open and re-save the table in Word so a plain <w:tbl> opening tag exists before the placeholder.","Unzip the docx and verify '<w:tbl>' precedes the placeholder."],"exampleFix":"// before\n$processor->deleteRow('ItemRow'); // 'ItemRow' is a paragraph variable, not in a table -> throws\n// after\n$processor->setValue('ItemRow', 'value'); // paragraph variable handled with setValue","handlingStrategy":"validation","validationCode":"function isInTable(string $templatePath, string $var): bool {\n    $zip = new ZipArchive();\n    $zip->open($templatePath);\n    $xml = $zip->getFromName('word/document.xml');\n    $zip->close();\n    $pos = strpos($xml, '${' . $var . '}');\n    return $pos !== false && strrpos(substr($xml, 0, $pos), '<w:tbl>') !== false;\n}","typeGuard":null,"tryCatchPattern":"try {\n    $processor->deleteRow($var);\n} catch (\\PhpOffice\\PhpWord\\Exception\\Exception $e) {\n    if (str_contains($e->getMessage(), 'start position of the table')) {\n        $processor->setValue('${' . $var . '}', ''); // fallback: blank instead of delete\n    } else { throw $e; }\n}","preventionTips":["Verify each deleteRow target variable sits inside <w:tbl>/<w:tr> in document.xml.","Use setValue for paragraph-level variables, deleteRow only for table rows.","Regenerate templates in Word so standard table markup is present.","Automate a template lint step in CI that validates variable placement."],"tags":["phpword","template-processing","docx","xml"],"backgroundTag":"resource-not-found","analyzedSha":"aef95c04151b5633cc505f672ddd6a71da900ee1","analyzedAt":"2026-09-14T10:53:58.933Z","contentChangedAt":"2026-09-14T10:53:58.933Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}