PHPOffice/PHPWord · error · BadMethodCallException
Cannot add in .
Error message
Cannot add {$method} in {$this->container}. What it means
AbstractContainer::checkValidity() rejects adding an element type that is not valid for the current container at all. The $validContainers map defines which containers (Section, Cell, TextRun, Header, Footer, etc.) may hold each element type; adding e.g. a TextRun directly to a Cell that only accepts certain children throws this BadMethodCallException naming the method and container.
Solutions
- Move the add* call to the correct container (e.g. add TextRun to a Section, not a Cell if disallowed)
- Check the $validContainers rules in AbstractContainer.php for the element type you are adding
- Use TextRun as an intermediate container where direct addition is not allowed
- Restructure the document so the element belongs to an allowed parent
Example fix
// before
$cell->addTextRun(); // not allowed for Cell
// after
$textrun = $cell->addText();
$textrun->addText('nested content'); Defensive patterns
Strategy: try-catch
Validate before calling
$validMap = ['TextRun' => ['Section', 'Cell', 'TextRun', 'Header', 'Footer', 'Footnote']];
$containerType = (new ReflectionClass($container))->getShortName();
if (isset($validMap['TextRun']) && !in_array($containerType, $validMap['TextRun'], true)) {
// choose a different parent before adding
} Try / catch
use PhpOffice\PhpWord\Element\AbstractContainer;
try {
$container->addTextRun();
} catch (\BadMethodCallException $e) {
// fall back to adding to the parent Section
$section->addTextRun();
} Prevention
- Read the $validContainers array in AbstractContainer.php before nesting elements
- Model document structure per OOXML rules: TextRun in Section/Cell, Table in Section/Cell only
- Isolate document building in a builder class so container misuse is caught in one place
- Add smoke tests that build your document template end-to-end
When it happens
Trigger: Calling e.g. $cell->addTextRun(...), $textrun->addFootnote(...), or $section->addComment-style calls where the element method exists on the container class but is not listed for that container type in $validContainers. Triggered via any addElement() dispatch like addText, addImage, addTextRun on the wrong container.
Common situations: Trying to nest elements in ways OOXML does not allow (e.g. a Table inside a TextRun, a Footer inside a Cell); copying code from one container context to another; upgrading PhpWord where containment rules were tightened.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Invalid value, on of ' . implode(', ', $position) . '…
- Invalid value, on of ' . implode(', ', $restartNumbers) . '…
- Invalid value, dirty or clean possible
- Invalid value, alignments of ' . implode(', '…
- Cannot set a Comment on a Comment
AI-assisted analysis of PHPOffice/PHPWord@aef95c0415 (2026-09-14).
Data as JSON: /api/errors/282aee605a810e4b.
Report an issue: GitHub.
Appendix: source
Thrown at src/PhpWord/Element/AbstractContainer.php:275
'PreserveText' => ['Section', 'Header', 'Footer', 'Cell'],
'Title' => ['Section', 'Cell', 'Header'],
'TOC' => ['Section'],
'PageBreak' => ['Section'],
'Chart' => ['Section', 'Cell'],
];
// Special condition, e.g. preservetext can only exists in cell when
// the cell is located in header or footer
$validSubcontainers = [
'PreserveText' => [['Cell'], ['Header', 'Footer', 'Section']],
'Footnote' => [['Cell', 'TextRun'], ['Section']],
'Endnote' => [['Cell', 'TextRun'], ['Section']],
];
// Check if a method is valid for current container
if (isset($validContainers[$method])) {
if (!in_array($this->container, $validContainers[$method])) {
throw new BadMethodCallException("Cannot add {$method} in {$this->container}.");
}
}
// Check if a method is valid for current container, located in other container
if (isset($validSubcontainers[$method])) {
$rules = $validSubcontainers[$method];
$containers = $rules[0];
$allowedDocParts = $rules[1];
foreach ($containers as $container) {
if ($this->container == $container && !in_array($this->getDocPart(), $allowedDocParts)) {
throw new BadMethodCallException("Cannot add {$method} in {$this->container}.");
}
}
}
return true;
}
}View on GitHub (pinned to aef95c0415)