{"record":{"id":"f746d035b57c62e6","repo":"doctrine/orm","slug":"undefined-method-s-the-method-name-must-start","errorCode":null,"errorMessage":"Undefined method \"%s\". The method name must start with either findBy, findOneBy or countBy!","messagePattern":"Undefined method \"(.+?)\"\\. The method name must start with either findBy, findOneBy or countBy!","errorType":"exception","errorClass":"BadMethodCallException","httpStatus":null,"severity":"error","filePath":"src/EntityRepository.php","lineNumber":165,"sourceCode":"     * @phpstan-param list<mixed> $arguments\n     *\n     * @throws BadMethodCallException If the method called is invalid.\n     */\n    public function __call(string $method, array $arguments): mixed\n    {\n        if (str_starts_with($method, 'findBy')) {\n            return $this->resolveMagicCall('findBy', substr($method, 6), $arguments);\n        }\n\n        if (str_starts_with($method, 'findOneBy')) {\n            return $this->resolveMagicCall('findOneBy', substr($method, 9), $arguments);\n        }\n\n        if (str_starts_with($method, 'countBy')) {\n            return $this->resolveMagicCall('count', substr($method, 7), $arguments);\n        }\n\n        throw new BadMethodCallException(sprintf(\n            'Undefined method \"%s\". The method name must start with ' .\n            'either findBy, findOneBy or countBy!',\n            $method,\n        ));\n    }\n\n    /** @return class-string<T> */\n    protected function getEntityName(): string\n    {\n        return $this->entityName;\n    }\n\n    public function getClassName(): string\n    {\n        return $this->getEntityName();\n    }\n\n    protected function getEntityManager(): EntityManagerInterface","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/doctrine/orm/blob/d9b9ff73016bf598ae07515f97289ce8074e97a5/src/EntityRepository.php#L147-L183","documentation":"BadMethodCallException from EntityRepository::__call() (src/EntityRepository.php:165). EntityRepository intercepts undefined method names and turns them into magic finders, but only for the prefixes findBy*, findOneBy* and countBy*. Any other unreachable method name falls through to this exception naming the method you called.","triggerScenarios":"Calling a method on a repository that does not exist as a real method and does not start with (case-sensitive) 'findBy', 'findOneBy' or 'countBy' — e.g. $repo->findLatest(), $repo->deleteByStatus(), $repo->findbyName() (lowercase 'b'), $repo->findAllByStatus(), or a custom method invoked on the base EntityRepository instead of your subclass.","commonSituations":"Repository class not configured on the entity (#[Entity(repositoryClass: ...)] missing) so $em->getRepository() returns the generic EntityRepository and your custom methods disappear; typos/casing in magic finder names; expecting magic delete/update/findLatest finders that Doctrine never provided.","solutions":["If you expected a custom method: make sure getRepository() returns your subclass — set repositoryClass in the entity mapping (or use a repository factory).","For queries, use explicit methods: $repo->findBy(['status' => 'x'], ['createdAt' => 'DESC'], 10) or QueryBuilder.","Check spelling and casing: prefixes are case-sensitive (findOneBy..., findBy..., countBy...).","Add the missing finder as a real method on a custom repository class for anything non-trivial."],"exampleFix":"// before\n#[Entity]\nclass Product { }\n$repo = $em->getRepository(Product::class);\n$repo->findLatest(10); // BadMethodCallException: not findBy/findOneBy/countBy\n\n// after\n#[Entity(repositoryClass: ProductRepository::class)]\nclass Product { }\n\nfinal class ProductRepository extends EntityRepository {\n    public function findLatest(int $limit): array {\n        return $this->createQueryBuilder('p')\n            ->orderBy('p.createdAt', 'DESC')\n            ->setMaxResults($limit)\n            ->getQuery()->getResult();\n    }\n}","handlingStrategy":"type-guard","validationCode":"$allowed = static fn (string $m): bool =>\n    str_starts_with($m, 'findBy')\n    || str_starts_with($m, 'findOneBy')\n    || str_starts_with($m, 'countBy');\n\nif (! method_exists($repo, $method) && ! $allowed($method)) {\n    throw new BadMethodCallException(\"{$method} is not a valid magic finder on \" . $repo::class);\n}","typeGuard":"/** @param class-string<\\Doctrine\\ORM\\EntityRepository> $repoClass */\nfunction canCallRepositoryMethod(string $repoClass, string $method): bool\n{\n    if (method_exists($repoClass, $method)) {\n        return true;\n    }\n    return str_starts_with($method, 'findBy')\n        || str_starts_with($method, 'findOneBy')\n        || str_starts_with($method, 'countBy');\n}","tryCatchPattern":null,"preventionTips":["Always map entities with repositoryClass so custom methods exist as real methods.","Prefer explicit findBy()/findOneBy()/count() calls with array criteria over magic names in typed code.","Remember prefixes are case-sensitive: findOneBy..., findBy..., countBy...."],"tags":["doctrine-orm","repository","magic-methods","api-misuse"],"backgroundTag":"undefined-method-call","analyzedSha":"d9b9ff73016bf598ae07515f97289ce8074e97a5","analyzedAt":"2026-08-21T06:13:15.863Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}