yiisoft/yii2 · error · InvalidCallException
Unsetting an unknown or read-only property: {class}::{name}
Error message
Unsetting an unknown or read-only property: {class}::{name} What it means
Component::__unset() first tries the class itself (setter path), then asks each attached behavior via canSetProperty() and nulls the property on the first behavior that accepts it. Only when the class and every attached behavior refuse does it throw InvalidCallException('Unsetting an unknown or read-only property: C::p'). With Components the error therefore also means: no currently attached behavior provides that property.
Source
Thrown at framework/base/Component.php:292
*/
public function __unset($name)
{
$setter = 'set' . $name;
if (method_exists($this, $setter)) {
$this->$setter(null);
return;
}
// behavior property
$this->ensureBehaviors();
foreach ($this->_behaviors as $behavior) {
if ($behavior->canSetProperty($name)) {
$behavior->$name = null;
return;
}
}
throw new InvalidCallException('Unsetting an unknown or read-only property: ' . get_class($this) . '::' . $name);
}
/**
* Calls the named method which is not a class method.
*
* This method will check if any attached behavior has
* the named method and will execute it if available.
*
* 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
* @return mixed the method return value
* @throws UnknownMethodException when calling unknown method
*/
public function __call($name, $params)
{
$this->ensureBehaviors();View on GitHub (pinned to 66f00d18a2)
Solutions
- Inspect live behaviors with $model->getBehaviors() and compare with the intended behaviors() config; a missing behavior is the usual answer
- Use the class's explicit clearing API instead of unset()
- Add a setter on the component or on the behavior if null-clearing is a legitimate operation
Example fix
// before
$post = clone $basePost; // Component::__clone detaches behaviors
unset($post->slug); // slug came from SlugBehavior => throws
// after
$post->attachBehavior('slug', \app\behaviors\SlugBehavior::class);
unset($post->slug); // behavior now accepts the unset Defensive patterns
Strategy: validation
Validate before calling
if ($component->canSetProperty($name)) { // Component::canSetProperty also checks attached behaviors
unset($component->$name);
} Prevention
- Re-attach required behaviors after clone, or override __clone() to reattach them
- Keep behavior config declarative in behaviors() instead of runtime attach calls
- Prefer explicit clearing methods over unset() on behavior-provided properties
When it happens
Trigger: unset($model->someProp) where someProp was expected from a behavior that is not attached - typo in behaviors(), a conditional behavior disabled in the current scenario, or behaviors cleared by clone (Component::__clone resets them); cleanup loops unsetting dynamic properties before caching.
Common situations: Behavior-driven models whose behaviors() config drifted; cloned components later treated as if their behaviors survived the clone.
Related errors
- Unsetting read-only property: {class}::{name}
- Calling unknown method: {class}::{name}()
- 'Getting write-only property: ' . get_class($this) . '::' .
- Getting unknown property: {class}::{name}
- Setting read-only property: {class}::{name}
AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17).
Data as JSON: /api/errors/61220854f6e2f3da.
Report an issue: GitHub.