yiisoft/yii2 · error · InvalidCallException
Unable to locate view file for view '$view': no active contr
Error message
Unable to locate view file for view '$view': no active controller.
What it means
Thrown by yii\base\View::getViewFile() when a view name starts with a single slash (e.g. '/site/index'), which by convention resolves relative to the currently active controller's module view path. If Yii::$app->controller is null there is no active controller to anchor the resolution, so the lookup cannot proceed and an InvalidCallException is raised. Aliased ('@app/...') and '//'-prefixed (app view path) names never hit this branch.
Source
Thrown at framework/base/View.php:184
* the view file corresponding to a relative view name.
* @return string the view file path. Note that the file may not exist.
* @throws InvalidCallException if a relative view name is given while there is no active context to
* determine the corresponding view file.
*/
protected function findViewFile($view, $context = null)
{
if (strncmp($view, '@', 1) === 0) {
// e.g. "@app/views/main"
$file = Yii::getAlias($view);
} elseif (strncmp($view, '//', 2) === 0) {
// e.g. "//layouts/main"
$file = Yii::$app->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/');
} elseif (strncmp($view, '/', 1) === 0) {
// e.g. "/site/index"
if (Yii::$app->controller !== null) {
$file = Yii::$app->controller->module->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/');
} else {
throw new InvalidCallException("Unable to locate view file for view '$view': no active controller.");
}
} elseif ($context instanceof ViewContextInterface) {
$file = $context->getViewPath() . DIRECTORY_SEPARATOR . $view;
} elseif (($currentViewFile = $this->getRequestedViewFile()) !== false) {
$file = dirname($currentViewFile) . DIRECTORY_SEPARATOR . $view;
} else {
throw new InvalidCallException("Unable to resolve view file for view '$view': no active view context.");
}
if (pathinfo($file, PATHINFO_EXTENSION) !== '') {
return $file;
}
$path = $file . '.' . $this->defaultExtension;
if ($this->defaultExtension !== 'php' && !is_file($path)) {
$path = $file . '.php';
}
return $path;View on GitHub (pinned to 66f00d18a2)
Solutions
- Use a path alias instead: render('@app/views/site/index', ...) — alias names are controller-independent.
- Pass a $context object implementing yii\base\ViewContextInterface as the second argument to render(), so relative resolution anchors to its getViewPath().
- For console apps that must reuse controller-style paths, set an active controller first or keep shared partials under an aliased directory.
Example fix
// before (inside a console command or queue job)
echo Yii::$app->view->render('/emails/welcome', ['user' => $user]);
// no active controller in console context -> InvalidCallException
// after
echo Yii::$app->view->render('@app/views/emails/welcome', ['user' => $user]); Defensive patterns
Strategy: validation
Validate before calling
// In controller-less contexts (console/queue), never use '/'-prefixed view names
if (Yii::$app->controller === null) {
$viewName = '@app/views' . $viewName; // '/site/index' -> '@app/views/site/index'
}
return Yii::$app->view->render($viewName, $params, $context); Prevention
- Use '@app/views/...' aliases in all code that can run outside a request (console commands, queue jobs, mailers)
- Pass an explicit ViewContextInterface context to render() in services
- Add a console smoke test that renders every view used by background jobs
When it happens
Trigger: Calling Yii::$app->view->render('/emails/welcome', ...) from a console command, queue job, or during bootstrap when no controller was ever set; unit tests that render views without stubbing a controller; rendering from a cron handler or event subscriber in a web worker between requests.
Common situations: Email/view rendering moved from a controller action into a queue job or console command; developers reusing view paths written for controller context ('/site/partials/x') in background code; tests that construct View directly.
Related errors
- Unable to resolve view file for view '$view': no active view
- The "basePath" property must be set.
- The view file does not exist: $viewFile
- Expecting end() of {widget}, found {calledClass}
- Unexpected {calledClass}::end() call. A matching begin() is
AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17).
Data as JSON: /api/errors/3b0fb6842c12a171.
Report an issue: GitHub.