symfony/routing · error · BadMethodCallException
Method " " not found on " " when importing routing resource…
Error message
Method "%s" not found on "%s" when importing routing resource "%s".
What it means
After resolving the object and method name from the resource string, ObjectLoader::load() verifies the method is callable on the loaded object. If not, it throws BadMethodCallException reporting the method name, the resolved object's type, and the original resource string, so the loader never calls an undefined method.
Solutions
- Correct the method name in the resource string to match a real public method on the service
- Add an __invoke method to the class if you intend to call the service directly
- Verify which class the service id resolves to (debug:container) — the error message shows get_debug_type of the actual object
- If the method was renamed, update the routing config to the new name
Example fix
# before
app_routes:
resource: 'app.routing.loader::routeLoader'
type: service
# after (method exists as loadRoutes on the service)
app_routes:
resource: 'app.routing.loader::loadRoutes'
type: service Defensive patterns
Strategy: type-guard
Validate before calling
$id = explode('::', $resource)[0];
$obj = $container->get($id);
$method = explode('::', $resource)[1] ?? '__invoke';
if (!is_callable([$obj, $method])) { /* fix method name before calling the loader */ } Type guard
function isCallableLoader(object $obj, string $method): bool { return is_callable([$obj, $method]); } Try / catch
try { $collection = $loader->load($resource, 'service'); } catch (\BadMethodCallException $e) { /* correct method name or add __invoke per $e->getMessage() */ } Prevention
- Verify the method exists on the service before wiring it as a route loader
- Use final methods or interfaces to keep loader APIs stable and greppable
- Run debug:router or a smoke test that loads all routing files in CI
- Update routing configs in the same commit that renames loader methods
When it happens
Trigger: Resource 'object_id::method' where the service has no such method; resource 'object_id' where the class has no __invoke; typos in the method name; method renamed during refactoring while routing config was not updated.
Common situations: Renaming a loader method without updating routing.yaml; pointing at an interface id whose implementation lacks __invoke; service id resolving to a different class than expected (autowiring alias changed).
Related errors
- Cannot serialize Loader\Configurator\ImportConfigurator
- Cannot unserialize Loader\Configurator\ImportConfigurator
- Invalid resource " " passed to the route loader: use the…
- Parameter " " for route " " must match " " (" " given) to…
- Parameters for route
AI-assisted analysis of symfony/routing@83fa223250 (2026-09-14).
Data as JSON: /api/errors/df8901f7d639e62d.
Report an issue: GitHub.
Appendix: source
Thrown at Loader/ObjectLoader.php:48
*/
abstract protected function getObject(string $id): object;
/**
* Calls the object method that will load the routes.
*/
public function load(mixed $resource, ?string $type = null): RouteCollection
{
if (!preg_match('/^[^\:]+(?:::(?:[^\:]+))?$/', $resource)) {
throw new \InvalidArgumentException(\sprintf('Invalid resource "%s" passed to the %s route loader: use the format "object_id::method" or "object_id" if your object class has an "__invoke" method.', $resource, \is_string($type) ? '"'.$type.'"' : 'object'));
}
$parts = explode('::', $resource);
$method = $parts[1] ?? '__invoke';
$loaderObject = $this->getObject($parts[0]);
if (!\is_callable([$loaderObject, $method])) {
throw new \BadMethodCallException(\sprintf('Method "%s" not found on "%s" when importing routing resource "%s".', $method, get_debug_type($loaderObject), $resource));
}
$routeCollection = $loaderObject->$method($this, $this->env);
if (!$routeCollection instanceof RouteCollection) {
$type = get_debug_type($routeCollection);
throw new \LogicException(\sprintf('The "%s::%s()" method must return a RouteCollection: "%s" returned.', get_debug_type($loaderObject), $method, $type));
}
// make the object file tracked so that if it changes, the cache rebuilds
$this->addClassResource(new \ReflectionClass($loaderObject), $routeCollection);
return $routeCollection;
}
private function addClassResource(\ReflectionClass $class, RouteCollection $collection): void
{View on GitHub (pinned to 83fa223250)