yiisoft/yii2 · error · InvalidConfigException

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

Error message

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

What it means

yii\di\Instance::ensure() fell through all accepted reference shapes - the value is not an array config, not a string ID, not an Instance, and not an object of the expected type - so it reports the actual PHP type it received ('Invalid data type: integer. ... is expected.'). It is the terminal guard of ensure(): whatever was passed can never denote a component.

Source

Thrown at framework/di/Instance.php:166

        } 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;
            }

            throw new InvalidConfigException('"' . $reference->id . '" refers to a ' . get_class($component) . " component. $type is expected.");
        }

        $valueType = is_object($reference) ? get_class($reference) : gettype($reference);
        throw new InvalidConfigException("Invalid data type: $valueType. $type is expected.");
    }

    /**
     * Returns the actual object referenced by this Instance object.
     * @param ServiceLocator|Container|null $container the container used to locate the referenced object.
     * If null, the method will first try `Yii::$app` then `Yii::$container`.
     * @return object|null the actual object referenced by this Instance object.
     */
    public function get($container = null)
    {
        try {
            if ($container) {
                return $container->get($this->id);
            }
            if (Yii::$app && Yii::$app->has($this->id)) {
                return Yii::$app->get($this->id);
            }

View on GitHub (pinned to 66f00d18a2)

Solutions

  1. Pass a valid reference: a component ID string, a config array with 'class', an Instance, or an object instance.
  2. Validate/normalize external input before it reaches the component setter (is_string/is_array checks).
  3. Cast or map scalar settings to a real configuration, e.g. 5 → ['class' => FileCache::class, 'cachePath' => ...].
  4. Fix the source of the wrong type (config schema, JSON contract).

Example fix

// before
$cache = Instance::ensure(5, yii\caching\CacheInterface::class);

// after
$cache = Instance::ensure('cache', yii\caching\CacheInterface::class);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!is_string($value) && !is_array($value) && !is_object($value)) {
    throw new \InvalidArgumentException('Component reference must be a string ID, config array, or object; got ' . gettype($value));
}
$component = \yii\di\Instance::ensure($value, $type);

Type guard

/** Narrows anything a config source can yield to a valid Instance::ensure() reference. */
function toReference($value)
{
    if (is_string($value) && $value !== '') {
        return $value;
    }
    if (is_array($value) && isset($value['__class'], $value['class']) === false && isset($value['class'])) {
        return $value;
    }
    if (is_object($value) && !($value instanceof \Closure)) {
        return $value;
    }
    return null; // caller decides the default
}

Try / catch

try {
    $component = \yii\di\Instance::ensure($raw, $type);
} catch (\yii\base\InvalidConfigException $e) {
    if (strpos($e->getMessage(), 'Invalid data type:') === 0) {
        // normalize: fall back to the default component ID
        $component = \yii\di\Instance::ensure('cache', $type);
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: Instance::ensure(5, Cache::class) or Instance::ensure(true, ...) - an int/bool/resource/float where a component reference is required; an untyped config value (e.g. from JSON or a DB field) passed straight into a component-typed setter.

Common situations: Env/config values cast to scalars (feature flags parsed as int) funneled into component properties; JSON payloads where an object was expected but a scalar arrived; setter methods that accept mixed but forward to Instance::ensure without validation.

Related errors


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