The Repository Method That Never Existed
How a Spring Data habit became a Doctrine fatal error
Published Oct 29, 2026
Executive Summary
A login check calls findByEmailAndActive() on a Doctrine repository — a magic finder that only exists in Spring Data JPA, where the framework generates the query from the method name. Doctrine has no such convention, so the method is undefined and the very first login crashes with a fatal error. The fix is Doctrine's real API: findOneBy() with a criteria array.
The Prompt
“Add a method to the UserRepository that looks up a user by email and active status for the login check.”
The Flaw
findByEmailAndActive() is a Spring Data JPA idiom — in that world, the framework derives the query from the method name and implements it for you. Doctrine has no such convention: repository methods must be written by hand. Because PHP resolves method calls at runtime, the file passes php -l, the class autoloads cleanly, and nothing fails until the login check actually runs — at which point PHP throws 'Call to undefined method App\Repository\UserRepository::findByEmailAndActive()'.
Risk & Impact
[Availability] The very first production login crashes with a fatal 'Call to undefined method' error. The method name looked exactly like the kind of thing a framework would auto-implement, so nobody questioned it — until a real user hit it.
Cost: Login feature dead on arrival; the error only surfaces with real traffic because no test or static check ever executed that code path.
Code Comparison
❌ Vulnerable (AI generated)
❌ Vulnerable (AI generated)
✅ Hardened (production ready)
The Fix
Use Doctrine's actual API — findOneBy()/findBy() with a criteria array, or a QueryBuilder — instead of inventing Spring Data-style magic finder names the ORM does not implement.
Prevention
- [linter] PHPStan or Psalm at level max flags 'Call to an undefined method' at CI time, so the hallucinated finder never reaches production.
- [ci] One smoke test that instantiates the repository and calls the finder fails fast, before any deploy.
- [manual] Name the ORM and version in the prompt (rule 1), and point the agent at an existing repository method to mirror instead of letting it guess the data-access API.
Why This Happened
Root cause: the prompt omitted Rule 1, Rule 7, and Rule 9 — the guardrails that would have caught this. See the full guide →
