yiisoft/yii2 · error · InvalidConfigException

Invalid data type: $class. $type is expected.

Error message

Invalid data type: $class. $type is expected.

What it means

yii\di\Instance::ensure() resolved the given array configuration through the container, but the resulting object is not an instance of the expected $type. ensure() is Yii's mechanism for accepting either a component ID, a config array, or an object wherever a component of a certain class/interface is required; when the array's '__class'/'class' entry produces an incompatible object, it throws InvalidConfigException naming the class it got and the type it expected.

Source

Thrown at framework/di/Instance.php:141

        if (is_array($reference)) {
            if (!$container instanceof Container) {
                $container = Yii::$container;
            }
            if (isset($reference['__class'])) {
                $class = $reference['__class'];
                unset($reference['__class'], $reference['class']);
            } elseif (isset($reference['class'])) {
                $class = $reference['class'];
                unset($reference['class']);
            } else {
                $class = $type;
            }
            $component = $container->get($class, [], $reference);
            if ($type === null || $component instanceof $type) {
                return $component;
            }

            throw new InvalidConfigException('Invalid data type: ' . $class . '. ' . $type . ' is expected.');
        } elseif (empty($reference)) {
            throw new InvalidConfigException('The required component is not specified.');
        }

        if (is_string($reference)) {
            $reference = new static($reference);
        } elseif ($type === null || $reference instanceof $type) {
            return $reference;
        }

        if ($reference instanceof self) {
            try {
                $component = $reference->get($container);
            } catch (\ReflectionException $e) {
                throw new InvalidConfigException('Failed to instantiate component or class "' . $reference->id . '".', 0, $e);
            }
            if ($type === null || $component instanceof $type) {
                return $component;

View on GitHub (pinned to 66f00d18a2)

Solutions

  1. Set '__class'/'class' to a class that implements/subclasses the expected type (e.g. a Mailer implementation for a mailer slot).
  2. If you have a custom implementation, make it extend/implement the expected base class or interface.
  3. Register the object under a component ID and pass the ID string instead of an inline array, after fixing the registration.
  4. Remove an overly specific Instance::ensure() type constraint if any implementation is actually acceptable.

Example fix

// before - property expects yii\mail\MailerInterface
'mailer' => ['__class' => app\components\SmsSender::class],

// after
'mailer' => ['__class' => yii\swiftmailer\Mailer::class],
// or make SmsSender implement yii\mail\MailerInterface
Defensive patterns

Strategy: type-guard

Validate before calling

// before passing an inline config to a typed slot
if (is_array($config) && isset($config['class']) && !is_subclass_of($config['class'], $expectedType)) {
    throw new \InvalidArgumentException('Configured class does not satisfy ' . $expectedType);
}
$component = \yii\di\Instance::ensure($config, $expectedType);

Type guard

/** Narrows a mixed value to something Instance::ensure() can accept for $type. */
function isComponentReference($value, string $type): bool
{
    if ($value instanceof $type) {
        return true;
    }
    if (is_string($value)) {
        return Yii::$app->has($value) || class_exists($value);
    }
    if (is_array($value)) {
        $class = $value['__class'] ?? $value['class'] ?? null;
        return $class !== null && is_a($class, $type, true);
    }
    return false;
}

Try / catch

use yii\base\InvalidConfigException;

try {
    $mailer = \yii\di\Instance::ensure($config, \yii\mail\MailerInterface::class);
} catch (InvalidConfigException $e) {
    // message names the class produced vs expected - surface as a boot-time config error
    Yii::error($e->getMessage(), 'config');
    throw;
}

Prevention

When it happens

Trigger: Passing an inline config array to a typed component slot, e.g. 'mailer' => ['__class' => app\components\SmsSender::class] where the property is documented/typed as yii\mail\MailerInterface and validated via Instance::ensure($value, MailerInterface::class).

Common situations: Configuring framework components inline in config/web.php with the wrong class; swapping a component implementation that does not implement the required interface (custom cache, custom mailer); copy-pasted config between components with different base types.

Related errors


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