{"record":{"id":"df8901f7d639e62d","repo":"symfony/routing","slug":"method-s-not-found-on-s-when-importing-routing-resource-s","errorCode":null,"errorMessage":"Method \"%s\" not found on \"%s\" when importing routing resource \"%s\".","messagePattern":"Method \"(.+?)\" not found on \"(.+?)\" when importing routing resource \"(.+?)\"\\.","errorType":"exception","errorClass":"BadMethodCallException","httpStatus":null,"severity":"error","filePath":"Loader/ObjectLoader.php","lineNumber":48,"sourceCode":"     */\n    abstract protected function getObject(string $id): object;\n\n    /**\n     * Calls the object method that will load the routes.\n     */\n    public function load(mixed $resource, ?string $type = null): RouteCollection\n    {\n        if (!preg_match('/^[^\\:]+(?:::(?:[^\\:]+))?$/', $resource)) {\n            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'));\n        }\n\n        $parts = explode('::', $resource);\n        $method = $parts[1] ?? '__invoke';\n\n        $loaderObject = $this->getObject($parts[0]);\n\n        if (!\\is_callable([$loaderObject, $method])) {\n            throw new \\BadMethodCallException(\\sprintf('Method \"%s\" not found on \"%s\" when importing routing resource \"%s\".', $method, get_debug_type($loaderObject), $resource));\n        }\n\n        $routeCollection = $loaderObject->$method($this, $this->env);\n\n        if (!$routeCollection instanceof RouteCollection) {\n            $type = get_debug_type($routeCollection);\n\n            throw new \\LogicException(\\sprintf('The \"%s::%s()\" method must return a RouteCollection: \"%s\" returned.', get_debug_type($loaderObject), $method, $type));\n        }\n\n        // make the object file tracked so that if it changes, the cache rebuilds\n        $this->addClassResource(new \\ReflectionClass($loaderObject), $routeCollection);\n\n        return $routeCollection;\n    }\n\n    private function addClassResource(\\ReflectionClass $class, RouteCollection $collection): void\n    {","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/symfony/routing/blob/83fa223250b50f4f018c011e101c330e65ac63cc/Loader/ObjectLoader.php#L30-L66","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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"],"exampleFix":"# before\napp_routes:\n    resource: 'app.routing.loader::routeLoader'\n    type: service\n\n# after (method exists as loadRoutes on the service)\napp_routes:\n    resource: 'app.routing.loader::loadRoutes'\n    type: service","handlingStrategy":"type-guard","validationCode":"$id = explode('::', $resource)[0];\n$obj = $container->get($id);\n$method = explode('::', $resource)[1] ?? '__invoke';\nif (!is_callable([$obj, $method])) { /* fix method name before calling the loader */ }","typeGuard":"function isCallableLoader(object $obj, string $method): bool { return is_callable([$obj, $method]); }","tryCatchPattern":"try { $collection = $loader->load($resource, 'service'); } catch (\\BadMethodCallException $e) { /* correct method name or add __invoke per $e->getMessage() */ }","preventionTips":["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"],"tags":["symfony","routing","object-loader","bad-method-call"],"backgroundTag":"method-not-implemented","analyzedSha":"83fa223250b50f4f018c011e101c330e65ac63cc","analyzedAt":"2026-09-14T03:19:46.280Z","contentChangedAt":"2026-09-14T03:19:46.280Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}