{"record":{"id":"05e501866b1948ad","repo":"PHPOffice/PHPWord","slug":"can-not-find-the-start-position-of-the-row-to-clone","errorCode":null,"errorMessage":"Can not find the start position of the row to clone.","messagePattern":"Can not find the start position of the row to clone\\.","errorType":"exception","errorClass":"PhpOffice\\PhpWord\\Exception\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpWord/TemplateProcessor.php","lineNumber":1253,"sourceCode":"        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     *\n     * @return int\n     */\n    protected function findRowStart($offset)\n    {\n        $rowStart = strrpos($this->tempDocumentMainPart, '<w:tr ', ((strlen($this->tempDocumentMainPart) - $offset) * -1));\n\n        if (!$rowStart) {\n            $rowStart = strrpos($this->tempDocumentMainPart, '<w:tr>', ((strlen($this->tempDocumentMainPart) - $offset) * -1));\n        }\n        if (!$rowStart) {\n            throw new Exception('Can not find the start position of the row to clone.');\n        }\n\n        return $rowStart;\n    }\n\n    /**\n     * Find the end position of the nearest table row after $offset.\n     *\n     * @param int $offset\n     *\n     * @return int\n     */\n    protected function findRowEnd($offset)\n    {\n        return strpos($this->tempDocumentMainPart, '</w:tr>', $offset) + 7;\n    }\n\n    /**","sourceCodeStart":1235,"sourceCodeEnd":1271,"githubUrl":"https://github.com/PHPOffice/PHPWord/blob/aef95c04151b5633cc505f672ddd6a71da900ee1/src/PhpWord/TemplateProcessor.php#L1235-L1271","documentation":"findRowStart() searches backwards from the placeholder offset for the opening row tag '<w:tr ' or '<w:tr>'. If neither is found it throws. cloneRow()/deleteRow() need the full row element boundaries to duplicate/remove it, so a missing row start means the placeholder is not in a table row.","triggerScenarios":"cloneRow() or deleteRow() called with a variable that is not inside a <w:tr> element — e.g. it sits in the table header/caption, outside any table, or the row markup was removed by hand-editing the template.","commonSituations":"Variable placed in a table caption or header rather than a body row; cloneRow used on a body-level variable; hand-edited template XML where row markup was removed.","solutions":["Ensure the placeholder is the content of a cell inside a normal <w:tr> row.","Add a dedicated template row containing just the variable for cloning.","Validate by unzipping the docx and checking document.xml for '<w:tr' before the variable.","Fall back to setValue or manual XML manipulation if the row structure is nonstandard."],"exampleFix":"// before\n$processor->cloneRow('headerVar', 3); // headerVar sits in the table header -> throws\n// after\n$processor->cloneRow('rowVar', 3); // rowVar is inside a body row <w:tr><w:tc><w:t>rowVar</w:t>...","handlingStrategy":"validation","validationCode":"function rowVariableExists(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    if ($pos === false) return false;\n    $before = substr($xml, 0, $pos);\n    return strrpos($before, '<w:tr ') !== false || strrpos($before, '<w:tr>') !== false;\n}","typeGuard":null,"tryCatchPattern":"try {\n    $processor->cloneRow($var, $count);\n} catch (\\PhpOffice\\PhpWord\\Exception\\Exception $e) {\n    if (str_contains($e->getMessage(), 'start position of the row')) {\n        error_log(\"Variable $var is not inside a table row\");\n    } else { throw $e; }\n}","preventionTips":["Keep clone target variables in dedicated body rows of tables, not headers/captions.","Lint templates in CI: assert each row variable has a <w:tr before it.","Keep the variable as plain single-run text within one cell.","Avoid hand-editing template XML in ways that remove row markup."],"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"}