yiisoft/yii2 · error · yii\base\InvalidConfigException

Invalid link: it must be an array of key-value pairs.

Error message

Invalid link: it must be an array of key-value pairs.

What it means

populateRelation() requires the relation query's link property to be an array of key-value pairs mapping primary-model columns to related-model columns. hasMany()/hasOne() normally set it, but when a relation getter passes a non-array $link, or a hand-built ActiveQuery never sets ->link, InvalidConfigException is thrown the moment the relation is populated, eagerly (joinWith/with) or lazily.

Source

Thrown at framework/db/ActiveRelationTrait.php:229

                    $modelClass = $this->modelClass;
                    $inverseRelation = $modelClass::instance()->getRelation($this->inverseOf);
                }
                $result[$i][$this->inverseOf] = $inverseRelation->multiple ? [$this->primaryModel] : $this->primaryModel;
            }
        }
    }

    /**
     * Finds the related records and populates them into the primary models.
     * @param string $name the relation name
     * @param array $primaryModels primary models
     * @return array the related models
     * @throws InvalidConfigException if [[link]] is invalid
     */
    public function populateRelation($name, &$primaryModels)
    {
        if (!is_array($this->link)) {
            throw new InvalidConfigException('Invalid link: it must be an array of key-value pairs.');
        }

        if ($this->via instanceof self) {
            // via junction table
            /** @var self<ActiveRecord|array<string, mixed>> $viaQuery */
            $viaQuery = $this->via;
            $viaModels = $viaQuery->findJunctionRows($primaryModels);
            $this->filterByModels($viaModels);
        } elseif (is_array($this->via)) {
            // via relation
            /** @var self<ActiveRecord|array<string, mixed>>|ActiveQueryTrait $viaQuery */
            list($viaName, $viaQuery) = $this->via;
            if ($viaQuery->asArray === null) {
                // inherit asArray from primary query
                $viaQuery->asArray($this->asArray);
            }
            $viaQuery->primaryModel = null;
            $viaModels = array_filter($viaQuery->populateRelation($viaName, $primaryModels));

View on GitHub (pinned to 66f00d18a2)

Solutions

  1. Pass the link as an array: $this->hasMany(Item::class, ['order_id' => 'id']) where the key is the related table's column and the value the primary table's column
  2. Audit every getXyz() relation getter in the involved model for a malformed link argument
  3. For manually constructed relation queries, set ->link explicitly to an array before returning them

Example fix

// before
public function getItems()
{
    return $this->hasMany(Item::class, 'order_id'); // string link -> throws on populate
}

// after
public function getItems()
{
    return $this->hasMany(Item::class, ['order_id' => 'id']);
}
Defensive patterns

Strategy: validation

Validate before calling

// sanity-check a relation definition before heavy use
$relation = $model->getItems();
if (!is_array($relation->link) || $relation->link === []) {
    throw new InvalidConfigException('Relation getItems() must define an array link.');
}

Try / catch

try {
    $items = $order->items;
} catch (yii\base\InvalidConfigException $e) {
    if (strpos($e->getMessage(), 'Invalid link') === 0) {
        throw new RuntimeException('Broken relation definition in ' . get_class($order) . '::getItems()', 0, $e);
    }
    throw $e;
}

Prevention

When it happens

Trigger: Defining return $this->hasMany(Item::class, 'order_id') (string link) instead of ['order_id' => 'id']; building an ActiveQuery manually for a relation and forgetting ->link = [...]; calling joinWith('malformedRelation') where the getter returns such a query.

Common situations: Habits carried from other AR libraries where a single string names the foreign key; incomplete copy-paste of relation examples; refactoring relation getters and dropping the array brackets.

Related errors


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