doctrine/orm · error · LogicException
This class requires PHP 8.4 or higher.
Error message
This class requires PHP 8.4 or higher.
What it means
RawValuePropertyAccessor is built on ReflectionProperty::setRawValueWithoutLazyInitialization(), an API that only exists in PHP 8.4+, so its constructor guards with a PHP_VERSION_ID check and throws LogicException on older runtimes. PropertyAccessorFactory only instantiates it on PHP >= 8.4, so seeing this error means the class was instantiated directly (or a cached container/metadata built on 8.4) on an older PHP.
Source
Thrown at src/Mapping/PropertyAccessors/RawValuePropertyAccessor.php:35
*
* It works based on the raw values of a property, which for a case of property hooks
* is the backed value. If we kept using setValue/getValue, this would go through the hooks,
* which potentially change the data.
*/
class RawValuePropertyAccessor implements PropertyAccessor
{
public static function fromReflectionProperty(ReflectionProperty $reflectionProperty): self
{
$name = $reflectionProperty->getName();
$key = $reflectionProperty->isPrivate() ? "\0" . ltrim($reflectionProperty->getDeclaringClass()->getName(), '\\') . "\0" . $name : ($reflectionProperty->isProtected() ? "\0*\0" . $name : $name);
return new self($reflectionProperty, $key);
}
private function __construct(private ReflectionProperty $reflectionProperty, private string $key)
{
if (PHP_VERSION_ID < 80400) {
throw new LogicException('This class requires PHP 8.4 or higher.');
}
}
public function setValue(object $object, mixed $value): void
{
if (! ($object instanceof InternalProxy && ! $object->__isInitialized())) {
$this->reflectionProperty->setRawValueWithoutLazyInitialization($object, $value);
return;
}
$object->__setInitialized(true);
$this->reflectionProperty->setRawValue($object, $value);
$object->__setInitialized(false);
}
View on GitHub (pinned to d9b9ff7301)
Solutions
- Do not instantiate RawValuePropertyAccessor yourself — use PropertyAccessorFactory::createPropertyAccessor(), which falls back to ObjectCastPropertyAccessor below PHP 8.4.
- Upgrade the runtime to PHP 8.4+ if your stack genuinely requires raw-value writes.
- When downgrading PHP, clear cached containers/metadata (var/cache/*, doctrine cache) so no 8.4-built services are unserialized on the older runtime.
Example fix
// before $accessor = RawValuePropertyAccessor::fromReflectionProperty($refl); // on PHP 8.3 -> LogicException // after use Doctrine\ORM\Mapping\PropertyAccessors\PropertyAccessorFactory; $accessor = PropertyAccessorFactory::createPropertyAccessor($class, $property); // picks the right accessor per PHP version
Defensive patterns
Strategy: validation
Validate before calling
if (PHP_VERSION_ID < 80400) {
// do not construct RawValuePropertyAccessor on this runtime
$accessor = PropertyAccessorFactory::createPropertyAccessor($class, $prop);
} Prevention
- Never instantiate RawValuePropertyAccessor directly; use PropertyAccessorFactory.
- Keep build and runtime PHP versions aligned in the deploy pipeline.
- Clear cached containers/metadata after changing the PHP version.
When it happens
Trigger: Directly calling new RawValuePropertyAccessor(...) or RawValuePropertyAccessor::fromReflectionProperty(...) on PHP < 8.4; deploying serialized service containers or cached metadata produced on a PHP 8.4 build to a PHP 8.1-8.3 runtime; custom code that copied PropertyAccessorFactory's logic without the version branch.
Common situations: Mixed-version deploy pipelines (build on latest PHP, run on older); downgrading a server's PHP without clearing var/cache; custom property-accessor wiring in bundles.
Related errors
- %s::$%s must be readonly property
- Attempting to change readonly property %s::$%s.
- %s::$%s must have a type when used with TypedNoDefaultProper
- %s::$%s must not be nullable when used with TypedNoDefaultPr
- Uninitialized result set mapping.
AI-assisted analysis of doctrine/orm@d9b9ff7301 (2026-08-21).
Data as JSON: /api/errors/fd90afc1cb401db8.
Report an issue: GitHub.