yiisoft/yii2 · error · InvalidCallException
Unsetting read-only property: {class}::{name}
Error message
Unsetting read-only property: {class}::{name} What it means
unset() on an inaccessible property triggers BaseObject::__unset(): if a setter exists it is called with null; if only a getter exists the property is read-only and InvalidCallException('Unsetting read-only property: C::p') is thrown. Note that for completely unknown names __unset() does nothing silently - only the read-only case throws, so this error always means a getter-only property met an unset().
Source
Thrown at framework/base/BaseObject.php:207
/**
* Sets an object property to null.
*
* Do not call this method directly as it is a PHP magic method that
* will be implicitly called when executing `unset($object->property)`.
*
* Note that if the property is not defined, this method will do nothing.
* If the property is read-only, it will throw an exception.
* @param string $name the property name
* @throws InvalidCallException if the property is read only.
* @see https://www.php.net/manual/en/function.unset.php
*/
public function __unset($name)
{
$setter = 'set' . $name;
if (method_exists($this, $setter)) {
$this->$setter(null);
} elseif (method_exists($this, 'get' . $name)) {
throw new InvalidCallException('Unsetting read-only property: ' . get_class($this) . '::' . $name);
}
}
/**
* Calls the named method which is not a class method.
*
* Do not call this method directly as it is a PHP magic method that
* will be implicitly called when an unknown method is being invoked.
* @param string $name the method name
* @param array $params method parameters
* @throws UnknownMethodException when calling unknown method
* @return mixed the method return value
*/
public function __call($name, $params)
{
throw new UnknownMethodException('Calling unknown method: ' . get_class($this) . "::$name()");
}
View on GitHub (pinned to 66f00d18a2)
Solutions
- Call the class's own clearing method, or clear via a setter instead of unset()
- Add a setter if setting null is a meaningful operation for the class
- Skip the unset when !$object->canSetProperty($name)
Example fix
// before unset($report->generatedAt); // getter only => InvalidCallException // after $report->clearGeneratedAt(); // explicit class method, or add setGeneratedAt(null) support
Defensive patterns
Strategy: validation
Validate before calling
if ($object->canSetProperty($name)) {
unset($object->$name); // routes through the setter with null
}
// read-only properties are left untouched - no exception Prevention
- Do not port array-cleanup unset() loops onto objects verbatim
- Expose explicit clear/reset methods on classes whose state must be clearable
- Guard unsets with canSetProperty() in generic serialization helpers
When it happens
Trigger: unset($report->generatedAt) where only getGeneratedAt() exists; generic cleanup code that unsets fields before caching or serializing an object; array-hygiene routines (where unset is always safe) reused on objects with computed getters.
Common situations: Serialization slimming that strips computed getters before var_export/json_encode; refactors from array payloads to objects that kept the old unset() calls.
Related errors
- 'Getting write-only property: ' . get_class($this) . '::' .
- Getting unknown property: {class}::{name}
- Setting read-only property: {class}::{name}
- Unsetting an unknown or read-only property: {class}::{name}
- Setting unknown property: {class}::{name}
AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17).
Data as JSON: /api/errors/792369022c9d4fd7.
Report an issue: GitHub.