yiisoft/yii2 · error · yii\base\InvalidConfigException

Value must be convertable to string.

Error message

Value must be convertable to string.

What it means

When a relation is populated, ActiveRelationTrait::filterByModels() hashes the primary models' key values through normalizeModelKey(), which casts each value to string. Since 2.0.40 non-string values must be convertible; casting an array or an object without __toString() raises an engine error that the catch (\Exception) branch converts into InvalidConfigException with the message 'Value must be convertable to string.'

Source

Thrown at framework/db/ActiveRelationTrait.php:613

            }
        }
        if (count($key) > 1) {
            return serialize($key);
        }
        return reset($key);
    }

    /**
     * @param mixed $value raw key value. Since 2.0.40 non-string values must be convertible to string (like special
     * objects for cross-DBMS relations, for example: `|MongoId`).
     * @return string normalized key value.
     */
    private function normalizeModelKey($value)
    {
        try {
            return (string)$value;
        } catch (\Exception $e) {
            throw new InvalidConfigException('Value must be convertable to string.');
        } catch (\Throwable $e) {
            throw new InvalidConfigException('Value must be convertable to string.');
        }
    }

    /**
     * @param array $primaryModels either array of AR instances or arrays
     * @return array
     */
    private function findJunctionRows($primaryModels)
    {
        if (empty($primaryModels)) {
            return [];
        }
        $this->filterByModels($primaryModels);
        /** @var ActiveRecord $primaryModel */
        $primaryModel = reset($primaryModels);
        if (!$primaryModel instanceof ActiveRecordInterface) {

View on GitHub (pinned to 66f00d18a2)

Solutions

  1. Ensure the linked attribute holds a scalar (string/int) before accessing or eagerly loading the relation
  2. Implement __toString() on custom key-object classes used in link columns
  3. Fix the relation's link definition so it targets a real scalar column, not a container attribute
  4. For lists of ids stored in one attribute, query manually with where(['id' => $array]) instead of a relation

Example fix

// before
public function getOrders()
{
    return $this->hasMany(Order::class, ['customer_id' => 'id']);
}
// $customer->id is an array (bad data) -> throws on $customer->orders

// after
$customer->id = (int) $raw; // normalize before relation access
$orders = $customer->orders;
Defensive patterns

Strategy: validation

Validate before calling

foreach ($models as $model) {
    $keyValue = $model->{$pkColumn};
    if (!is_scalar($keyValue) && !(is_object($keyValue) && method_exists($keyValue, '__toString'))) {
        throw new InvalidArgumentException('Relation key must be scalar or string-convertible.');
    }
}

Type guard

function isUsableRelationKey($value): bool
{
    return is_scalar($value) || (is_object($value) && method_exists($value, '__toString'));
}

Try / catch

try {
    $orders = $customer->orders;
} catch (yii\base\InvalidConfigException $e) {
    if (strpos($e->getMessage(), 'convertable to string') !== false) {
        // key attribute holds a non-scalar: fail loudly with the offending value
        throw new RuntimeException('Non-scalar relation key on customer.id', 0, $e);
    }
    throw $e;
}

Prevention

When it happens

Trigger: A relation's link points at an attribute that currently holds an array (e.g. a JSON column decoded to an array) or an object lacking __toString(); using relation methods with model instances whose key attributes were filled from unvalidated form input.

Common situations: JSON columns storing identifiers; upgrading from Yii < 2.0.40 where the cast silently produced garbage instead of an exception; custom key objects (cross-DBMS, e.g. MongoId-like classes) that never implemented __toString().

Related errors


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