I'm blogging about Emacs, Drupal, php and exciting subjects

I Installed drupal/redirect for Four URLs. It Redirected Every Node Path on the Site.

I had exactly four URLs I wanted redirected. Two articles had accidentally been published twice in July under different titles — a mixup during the early days of the JSON:API publishing pipeline — and once I'd settled on which copy of each to keep, the other needed to 301 somewhere instead of just disappearing. Four source paths, four targets, done.

One Flag, 2,109 Lines: What -W Rewrites in composer.lock

The composer.json diff for the Drupal 10 to 11 upgrade on this site is thirteen lines: a handful of version constraints bumped, doctrine/annotations added back, symfony/runtime allow-listed. The composer.lock diff for that same commit is 2,109 lines changed — 1,416 insertions, 693 deletions, one file.

Composer Called It Abandoned. Drupal 11 Still Needed It.

Composer has a specific way of telling you a package is a bad long-term bet: when a dependency is marked abandoned on Packagist, the lock file itself records "abandoned": true against that package's entry, and every install or update that touches it prints a warning.

The JSON:API Route That 403s With No Reason String

There's a specific kind of unhelpful a 403 can be. Try to set a field you don't have permission for through Drupal's JSON:API and you get a real, actionable message back — something like "The current user is not allowed to POST the selected field (status). The 'administer nodes' permission is required." That's a 403 that tells you exactly what to go fix.

The Allow-Plugins Security Prompt Is Composer's Best Feature and Its Most Annoying One

Somewhere in the middle of upgrading this site from Drupal 10 to 11, composer require drupal/core-recommended:^11 stopped and refused to install anything at all, not because of a version conflict this time, but because one of the packages it needed to pull in, symfony/runtime, ships a Composer plugin, and Composer plugins don't get to run just because they're in the de

A Config Entity's UUID Is Its Real Identity, Not Its Machine Name

Every Drupal config entity has a machine name and a UUID, and it's easy to go a long time treating the machine name as the entity's actual identity, because it's the one you type — id: api_publisher, right there at the top of the YAML file, human-readable and stable. The UUID sits a couple of lines above it, a string nobody reads, that looks like it shouldn't matter.

The Difference Between 'Uninstalled' and 'Gone'

Drupal has two separate ideas of whether a module exists, and, unless something actively keeps them in sync, they're allowed to disagree with each other. One lives in core.extension config: is the module marked installed, does the database have its schema, does anything still reference its config objects.

Subscribe to Linkhub