yiisoft/yii2 · error · Exception
Could not load required service: {name}
Error message
Could not load required service: {name} What it means
Since 2.0.16 controllers resolve class-type-hinted action parameters as services, in order: application components ($app->has()/get() with the type name), module DI ($this->module->has()/get()), then Yii::$container; if the parameter is nullable, null is injected as a last resort. When nothing resolves and the parameter is required, parameter binding throws yii\base\Exception('Could not load required service: <paramName>') - the name in the message is the PHP parameter name.
Source
Thrown at framework/base/Controller.php:595
*/
final protected function bindInjectedParams(\ReflectionNamedType $type, $name, &$args, &$requestedParams)
{
// Since it is not a builtin type it must be DI injection.
$typeName = $type->getName();
if (($component = $this->module->get($name, false)) instanceof $typeName) {
$args[] = $component;
$requestedParams[$name] = 'Component: ' . get_class($component) . " \$$name";
} elseif ($this->module->has($typeName) && ($service = $this->module->get($typeName)) instanceof $typeName) {
$args[] = $service;
$requestedParams[$name] = 'Module ' . get_class($this->module) . " DI: $typeName \$$name";
} elseif (\Yii::$container->has($typeName) && ($service = \Yii::$container->get($typeName)) instanceof $typeName) {
$args[] = $service;
$requestedParams[$name] = "Container DI: $typeName \$$name";
} elseif ($type->allowsNull()) {
$args[] = null;
$requestedParams[$name] = "Unavailable service: $name";
} else {
throw new Exception('Could not load required service: ' . $name);
}
}
}
View on GitHub (pinned to 66f00d18a2)
Solutions
- Register the binding in the application config: 'container' => ['singletons' => [InvoiceRepositoryInterface::class => InvoiceRepository::class]] (or Yii::$container->setSingleton(...))
- If the service is optional, make the parameter nullable (InvoiceRepository $repo = null) - Yii then injects null instead of throwing
- If it is app-wide, configure it under 'components' so the application-component branch resolves it
- Verify the type-hint names a real, instantiable class
Example fix
// before
public function actionPdf(InvoiceRepositoryInterface $repo) { /* ... */ }
// Exception: Could not load required service: repo
// after (config/web.php)
'container' => [
'singletons' => [
\app\repositories\InvoiceRepositoryInterface::class => \app\repositories\InvoiceRepository::class,
],
], Defensive patterns
Strategy: validation
Validate before calling
use app\repositories\InvoiceRepositoryInterface;
if (!\Yii::$container->has(InvoiceRepositoryInterface::class)) {
\Yii::$container->setSingleton(InvoiceRepositoryInterface::class, InvoiceRepository::class);
}
// now the action's type-hinted parameter can resolve Try / catch
try {
Yii::$app->runAction($route);
} catch (\yii\base\Exception $e) {
if (strpos($e->getMessage(), 'Could not load required service') === 0) {
// a required DI binding is missing: register it and retry once
\Yii::$container->setSingleton($missingInterface, $concrete);
Yii::$app->runAction($route);
}
throw $e;
} Prevention
- Define all interface-to-concrete mappings once under the 'container' config key
- Keep an integration test that hits every DI-enabled action
- Make optional services nullable and required services explicitly registered
When it happens
Trigger: public function actionIndex(InvoiceRepositoryInterface $repo) with no container definition for the interface and no app component or module entry of that class name; hinting a concrete class whose own constructor dependencies cannot be autowired recursively; a type-hint naming a nonexistent or misspelled class (nothing can ever resolve it).
Common situations: Adopting action DI after reading docs or snippets without adding the 'container' config block; interfaces that each application must map to its own implementation; constructor changes in the service after a dependency update that break autowiring.
Related errors
- get_class($this) . ' must define a "run()" method.'
- Unknown bootstrapping component ID: $mixed
- Controller class must extend from \yii\base\Controller.
- Missing required parameter "$name" when calling "$funcName".
- Invalid data type: $class. $type is expected.
AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17).
Data as JSON: /api/errors/b04b9b748d0d4bca.
Report an issue: GitHub.