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

  1. Do not instantiate RawValuePropertyAccessor yourself — use PropertyAccessorFactory::createPropertyAccessor(), which falls back to ObjectCastPropertyAccessor below PHP 8.4.
  2. Upgrade the runtime to PHP 8.4+ if your stack genuinely requires raw-value writes.
  3. 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

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


AI-assisted analysis of doctrine/orm@d9b9ff7301 (2026-08-21). Data as JSON: /api/errors/fd90afc1cb401db8. Report an issue: GitHub.