symfony/http-kernel · error · InvalidArgumentException
Controller " " does neither exist as service nor as class.
Error message
Controller "%s" does neither exist as service nor as class.
What it means
This is a fallback validation error in the controller resolver: the requested controller string was first looked up as a container service (container->has failed), then instantiation as a plain class was attempted and threw an \Error that was not attributable to a removed controller or to required constructor arguments. The controller reference is unresolvable — typically a typo in the service id/class name, a class that cannot be autoloaded, or a controller never registered as a service.
Solutions
- Fix the class name/namespace in the route's _controller value
- Verify the class exists and composer dump-autoload has been run
- If it should be a service, register it with the correct id
- Check throwExceptionIfControllerWasRemoved hints — the id may be a removed private service
Example fix
// before
#[Route('/x', name: 'x', controller: 'App\Controller\ReportControler::index')]
// after
#[Route('/x', name: 'x', controller: 'App\Controller\ReportController::index')] Defensive patterns
Strategy: validation
Validate before calling
if (!class_exists($class) && !$container->has($id)) { throw new \RuntimeException("controller {$class} not found"); } Type guard
class_exists($controllerClass) || $container->has($controllerId)
Try / catch
try { $response = $kernel->handle($request); } catch (\InvalidArgumentException $e) { if (str_contains($e->getMessage(), 'does neither exist as service nor as class')) { /* fix _controller reference */ } throw $e; } Prevention
- Validate route _controller values in a CI route smoke test
- Run composer dump-autoload after adding classes
- Grep routes for controllers after renames/deletions
When it happens
Trigger: Referencing a controller string like App\Controller\MissingController::index (typo, wrong namespace, class not autoloaded) or a service id that does not exist, e.g. in a route _controller.
Common situations: Typos in route _controller values, deleted/renamed controller classes with stale routes, composer autoload not regenerated, or referring to a private/removed service id.
Related errors
- Controller " " cannot be fetched from the container because…
- The controller for URI
- Message built by getControllerError(): e.g. Function
- You can only pin one resolver per argument, but argument "$
- " ::resolve()" must yield at most one value for…
AI-assisted analysis of symfony/http-kernel@aa3a39d728 (2026-09-13).
Data as JSON: /api/errors/41f9258d32f44316.
Report an issue: GitHub.
Appendix: source
Thrown at Controller/ContainerControllerResolver.php:52
{
$class = ltrim($class, '\\');
if ($this->container->has($class)) {
return $this->container->get($class);
}
try {
return parent::instantiateController($class);
} catch (\Error $e) {
}
$this->throwExceptionIfControllerWasRemoved($class, $e);
if ($e instanceof \ArgumentCountError) {
throw new \InvalidArgumentException(\sprintf('Controller "%s" has required constructor arguments and does not exist in the container. Did you forget to define the controller as a service?', $class), 0, $e);
}
throw new \InvalidArgumentException(\sprintf('Controller "%s" does neither exist as service nor as class.', $class), 0, $e);
}
private function throwExceptionIfControllerWasRemoved(string $controller, \Throwable $previous): void
{
if ($this->container instanceof Container && isset($this->container->getRemovedIds()[$controller])) {
throw new \InvalidArgumentException(\sprintf('Controller "%s" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?', $controller), 0, $previous);
}
}
}
View on GitHub (pinned to aa3a39d728)