yiisoft/yii2 · error · InvalidCallException

'Getting write-only property: ' . get_class($this) . '::' .

Error message

'Getting write-only property: ' . get_class($this) . '::' . $name

What it means

yii\base\BaseObject implements properties via magic methods: __get() looks for a getXxx() method, then a setXxx() method. If only a setter exists the property is write-only by design, and reading it throws InvalidCallException('Getting write-only property: ...'). The class author exposed mutation but deliberately (or accidentally) provided no read path.

Source

Thrown at framework/base/BaseObject.php:139

    /**
     * Returns the value of an object property.
     *
     * Do not call this method directly as it is a PHP magic method that
     * will be implicitly called when executing `$value = $object->property;`.
     * @param string $name the property name
     * @return mixed the property value
     * @throws UnknownPropertyException if the property is not defined
     * @throws InvalidCallException if the property is write-only
     * @see __set()
     */
    public function __get($name)
    {
        $getter = 'get' . $name;
        if (method_exists($this, $getter)) {
            return $this->$getter();
        } elseif (method_exists($this, 'set' . $name)) {
            throw new InvalidCallException('Getting write-only property: ' . get_class($this) . '::' . $name);
        }

        throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '::' . $name);
    }

    /**
     * Sets value of an object property.
     *
     * Do not call this method directly as it is a PHP magic method that
     * will be implicitly called when executing `$object->property = $value;`.
     * @param string $name the property name or the event name
     * @param mixed $value the property value
     * @throws UnknownPropertyException if the property is not defined
     * @throws InvalidCallException if the property is read-only
     * @see __get()
     */
    public function __set($name, $value)
    {

View on GitHub (pinned to 66f00d18a2)

Solutions

  1. Read the class source: a differently-named getter (e.g. getTokenValue()) often exposes the same data
  2. If you own the class, add public function getX() { return $this->_x; }
  3. Otherwise stop reading the property - treat it as an input, not as observable state

Example fix

// before
class TokenStore extends \yii\base\BaseObject
{
    private $_key;
    public function setKey($k) { $this->_key = $k; }
}
$value = $store->key; // InvalidCallException: Getting write-only property

// after
public function getKey() { return $this->_key; }
$value = $store->key;
Defensive patterns

Strategy: type-guard

Validate before calling

if ($object->canGetProperty($name)) {
    $value = $object->$name;
} else {
    $value = null; // property is write-only or absent
}

Type guard

function hasReadAccess(\yii\base\BaseObject $object, string $name): bool
{
    return $object->canGetProperty($name);
}

Try / catch

try {
    $value = $object->$name;
} catch (\yii\base\InvalidCallException $e) {
    // 'Getting write-only property:' - use the setter-provided read API instead
    Yii::warning($e->getMessage());
    $value = null;
}

Prevention

When it happens

Trigger: echo $object->apiKey when only setApiKey() exists; reading configuration-holder properties of a component that accepts injection but stores the value internally; a getter removed during a major-version refactor while the setter remained.

Common situations: Configuration objects that are write-only by design; secret/token holders where reading is intentionally blocked; API drift after upgrading a vendor package.

Related errors


AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17). Data as JSON: /api/errors/dd60ab4915a03fcd. Report an issue: GitHub.