doctrine/orm · error · InvalidArgumentException

Field "%s" is not a valid field of the entity "%s" in PreUpd

Error message

Field "%s" is not a valid field of the entity "%s" in PreUpdateEventArgs.

What it means

InvalidArgumentException from PreUpdateEventArgs::assertValidField() (src/Event/PreUpdateEventArgs.php:93). getOldValue()/getNewValue()/setNewValue() only work with fields present in the entity's change set — the UnitOfWork computes changes before the PreUpdate event, and the args object wraps that computed change set. Asking for a field that was not changed (or does not exist) fails this assertion.

Source

Thrown at src/Event/PreUpdateEventArgs.php:93

    /**
     * Sets the new value of this field.
     */
    public function setNewValue(string $field, mixed $value): void
    {
        $this->assertValidField($field);

        $this->entityChangeSet[$field][1] = $value;
    }

    /**
     * Asserts the field exists in changeset.
     *
     * @throws InvalidArgumentException
     */
    private function assertValidField(string $field): void
    {
        if (! isset($this->entityChangeSet[$field])) {
            throw new InvalidArgumentException(sprintf(
                'Field "%s" is not a valid field of the entity "%s" in PreUpdateEventArgs.',
                $field,
                get_debug_type($this->getObject()),
            ));
        }
    }
}

View on GitHub (pinned to d9b9ff7301)

Solutions

  1. Guard every access with $args->hasChangedField($field) before calling getOldValue/getNewValue/setNewValue.
  2. If you must touch a field that is not part of the change set, mutate the entity and register it manually: $entity->setUpdatedAt(...); plus $args->setNewValue only for changed fields — or recompute via $em->getUnitOfWork()->computeChangeSet($args->getObject()).
  3. Double-check field spelling and case against the mapping (the exception prints the actual entity class).
  4. Avoid setting a value identical to the current one; the UnitOfWork will not mark it changed, so your guard matters.

Example fix

// before
public function preUpdate(PreUpdateEventArgs $args): void {
    $args->setNewValue('updatedAt', new DateTimeImmutable());
        // throws if 'updatedAt' itself did not change
}

// after
public function preUpdate(PreUpdateEventArgs $args): void {
    $entity = $args->getObject();
    $entity->setUpdatedAt(new DateTimeImmutable());
    // only inspect change-set fields through $args:
    if ($args->hasChangedField('status')) {
        $old = $args->getOldValue('status');
        // ...
    }
    $em = $args->getObjectManager();
    $em->getUnitOfWork()->recomputeSingleEntityChangeSet(
        $em->getClassMetadata($entity::class), $entity
    );
}
Defensive patterns

Strategy: validation

Validate before calling

if ($args->hasChangedField('status')) {
    $old = $args->getOldValue('status');
    $args->setNewValue('status', $newValue);
}

Try / catch

try {
    $old = $args->getOldValue($field);
} catch (\InvalidArgumentException $e) {
    // field not in this flush's change set — treat as 'no previous value'
    $old = null;
}

Prevention

When it happens

Trigger: Inside a preUpdate listener calling $args->setNewValue('status', ...) or $args->getOldValue('status') when 'status' is not in the change set: the new value equals the old one (field unchanged), the field name is misspelled/case-wrong, or you read fields of a related entity instead of the updated one. Also calling setNewValue for a field never set on the entity.

Common situations: Listeners that unconditionally do $args->setNewValue("updatedAt", new DateTime()) even when only unrelated columns changed; renaming entity fields without updating listeners; assuming getOldValue works for any field rather than only changed ones; comparing values with != so a no-op change reaches the listener.

Related errors


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