Where AI agents get Drupal wrong
AI agents fail at Drupal in predictable ways. The mistakes are not random: they cluster around the places where Drupal 11 diverges from older Drupal and from other frameworks. Knowing the catalog lets you set up the gates and prompts that catch each one before it reaches you.
What and why
Section titled “What and why”An agent’s output reflects its training data, which is a large body of code weighted toward what existed longest and appeared most. For Drupal that means older releases, Stack Overflow answers from years ago, and patterns borrowed from other PHP frameworks. The current Drupal 11 way, attributes and dependency injection and explicit cache metadata, is newer and thinner on the ground, so the agent’s confident first guess often reaches past it.
This is why agent failures are predictable rather than random. They are not bugs in reasoning; they are the average of the internet’s Drupal showing through. That predictability is useful: a fixed list of failures maps cleanly to a fixed set of gates.
Mental model
Section titled “Mental model”One sentence to keep: every agent failure is a stale or borrowed pattern, and the verification loop is the antidote.
Each item in the catalog below is either a pattern Drupal has moved on from (stale) or a pattern from another framework that does not fit Drupal (borrowed). Neither is a reasoning error you can prompt away entirely. Both are caught by a gate or a review step that knows current Drupal, which is why the loop matters more than any single clever prompt.
The catalog
Section titled “The catalog”Each failure has a tell you can spot in a diff and a gate or review step that catches it.
| Failure | The tell | Caught by |
|---|---|---|
| Hallucinated or renamed API | A method or service that does not exist, or a real one with the wrong signature | PHPStan; a failing test |
| Annotations instead of attributes | @Block, @FieldType in a docblock instead of #[Block(...)] | Review, or a grep for @Block-style annotations in CI; see attributes |
Procedural hooks in a .module file | function mymodule_entity_presave() instead of a #[Hook] method | Review; see object-oriented hooks for the hooks that stay procedural |
Static \Drupal:: in a class | \Drupal::service('...') where a constructor injection belongs | PHPCS (DrupalPractice) in blocks, forms, controllers, formatters, widgets, and services; review elsewhere. See services and DI |
| Missing cache metadata | A render array that varies but declares no tags, contexts, or max-age | Review; see caching |
| Raw SQL for content | \Drupal::database()->query() to read or write entities | Review; see entities |
| Missing config schema | New config with no matching *.schema.yml | A kernel test that installs the config (strict schema checking is on by default); review otherwise |
| Security shortcuts | Unsanitized output, or access checks faked to make a feature work | Review; see access |
| Deprecated core APIs | A call to a function or method core has marked deprecated | PHPStan deprecation rules |
The pattern across the table: hallucinated APIs, deprecated calls, static service calls in the common plugin and service classes, and missing schema fail a command. Stale patterns that still run, such as annotations and procedural hooks, and the judgment failures need human review. Name the current patterns in your AGENTS.md so the agent avoids them, and set up both the gates and the review.
Common misconceptions
Section titled “Common misconceptions”A better prompt would prevent these. A good prompt reduces them, and pointing the agent at a real example reduces them further. It does not eliminate them, because the agent regresses to its training under any ambiguity. The gates are what make the failures safe, not the prompt.
These mean the agent is bad at Drupal. The agent is competent at the mechanics and fast at the typing. It is uneven on which mechanics are current. That is a different problem, and it is solved by the verification loop rather than by avoiding agents.
Passing PHPCS and PHPStan means the code is right. Those gates catch hallucinated APIs, deprecated calls, and most static service calls. Annotations, procedural hooks, cache metadata, raw SQL, and security problems pass them. That is why review is a separate step.
Where to go next
Section titled “Where to go next”- Verify agent-generated Drupal code sets up the gates that catch the failures a command can detect.
- Review what the checks miss covers the judgment failures the gates miss.
- Modernize Your Code shows the correct, current form of each stale pattern above.
Was this page helpful?
Drupal is a registered trademark of Dries Buytaert.