symfony/http-kernel · error · InvalidArgumentException
Message built by getControllerError(): e.g. Function
Error message
Message built by getControllerError(): e.g. Function "%s" does not exist. / Controller class "%s" cannot be called without a method name. You need to implement "__invoke". / Class "%s" does not exist.
What it means
Symfony's ControllerResolver fails to turn a controller string into a callable, so it throws InvalidArgumentException with a message produced by getControllerError(). The message tells you whether the function/class does not exist, or whether the class is not callable without a method name (no __invoke). It is thrown in createController() when the controller string contains no '::' and instantiating it does not yield something callable.
Solutions
- Check that the controller string matches an existing class (correct namespace and spelling) and is a real class, not an abstract/interface.
- If the controller is a service, ensure the class is autowired/autoconfigured in services.yaml and the class implements __invoke or the route names a method via 'Class::method'.
- Run `php bin/console debug:router` and `php bin/console debug:container <class>` to verify the controller resolves.
- Add a __invoke() method or an explicit '::method' suffix to the controller definition.
Example fix
// before: routes.yaml
app_foo:
path: /foo
controller: App\Controller\FooController
// after
app_foo:
path: /foo
controller: App\Controller\FooController::index Defensive patterns
Strategy: validation
Validate before calling
if (!class_exists($controllerClass) && !str_contains($controllerString, '::')) {
throw new \InvalidArgumentException(sprintf('Controller "%s" must be "Class::method" or implement __invoke().', $controllerString));
} Type guard
if (!\is_callable([$controllerClass, $method]) && !\is_callable([new $controllerClass(), '__invoke'])) {
return null; // not a resolvable controller
} Try / catch
try {
$controller = $resolver->getController($request);
} catch (\InvalidArgumentException $e) {
$logger->error('Unresolvable controller: '.$e->getMessage());
return new Response('Not Found', 404);
} Prevention
- Always use 'Class::method' syntax or #[Route] attributes so the controller is explicit.
- Verify controllers with `php bin/console debug:router` after adding routes.
- Keep services.yaml autoconfigure/auto-wiring of controller classes enabled.
- Add a smoke test that matches every route name against class_exists + method_exists.
When it happens
Trigger: Route/service configured with a controller string like 'App\Controller\FooController' where the class does not exist, is not registered as a service (controller.service_arguments), or lacks a default method and does not implement __invoke(); passing a non-callable value to the resolver directly.
Common situations: Typo in controller class name in routes.yaml/attributes; controller class defined but not tagged for the service container (missing services.yaml autoconfigure); class exists but expects constructor arguments not resolvable from the container; framework version upgrade changing how controllers are resolved.
Understand the failure class
Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.
Related errors
- Controller " " does neither exist as service nor as class.
- Controller " " cannot be fetched from the container because…
- The controller for URI
- 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/0a91fd13870680dc.
Report an issue: GitHub.
Appendix: source
Thrown at Controller/ControllerResolver.php:118
if (!\is_callable($callable)) {
throw new \InvalidArgumentException(\sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$this->getControllerError($callable));
}
return $this->checkController($request, $callable);
}
/**
* Returns a callable for the given controller.
*
* @throws \InvalidArgumentException When the controller cannot be created
*/
protected function createController(string $controller): callable
{
if (!str_contains($controller, '::')) {
$controller = $this->instantiateController($controller);
if (!\is_callable($controller)) {
throw new \InvalidArgumentException($this->getControllerError($controller));
}
return $controller;
}
[$class, $method] = explode('::', $controller, 2);
try {
$controller = [$this->instantiateController($class), $method];
} catch (\Error|\LogicException $e) {
try {
if ((new \ReflectionMethod($class, $method))->isStatic()) {
return $class.'::'.$method;
}
} catch (\ReflectionException) {
throw $e;
}
View on GitHub (pinned to aa3a39d728)