Ontbrekende functies, nullwaarden en AI

By Sjoerd , 28 June 2025

Dit is een verslag van een dag werken met mijn collega AI. Ik heb 'm gevraagd om er zelf verslag van te doen.

Sommige dagen herinneren je eraan waarom webontwikkeling bloedirritant is. Vandaag was er zo eentje. Na het ogenschijnlijk onschuldige updaten van deze Drupal-site naar versie 11.2.2, belandden we in een kettingreactie van fouten die ons dwong om patches te maken, mediatypes te corrigeren en URL-logica opnieuw te bedenken.

Het probleem: een waterval aan waarschuwingen

Alles begon vredig. Een verse Drupal 11.2.2-installatie, alles werkte... tot we /admin/reports/status bezochten. In plaats van een overzicht kregen we een witte pagina met een klassieke PHP-fout. In de logboeken vonden we twee hoofdverdachten:

  • Fatal error: Call to undefined function drupal_verify_install_file()
  • Type error: Html::escape(): Argument #1 ($text) must be of type string, null given

Beide fouten voorkwamen dat we als beheerder nog iets zinnigs uit de statuspagina konden halen.

Onderzoek

De eerste fout bleek relatief eenvoudig te traceren. drupal_verify_install_file() werd aangeroepen vanuit system_requirements() in de system.install file, maar de bijbehorende include (install.inc) werd nooit geladen. Klassiek gevalletje "functie wel gebruiken, niet importeren".

De tweede fout was minder vriendelijk. Iemand, ergens, gaf een null-waarde door aan Html::escape() via een FormattableMarkup-object. De vraag: wie?

Oplossing 1: de ontbrekende include repareren

We ontdekten dat system.install de functie drupal_verify_install_file() probeerde te gebruiken zonder het bijbehorende bestand te includen. Tijd voor een patch.

--- core/modules/system/system.install
+++ core/modules/system/system.install
@@ -8,6 +8,8 @@
 use Drupal\Component\FileSystem\FileSystem as FileSystemComponent;
 use Drupal\Component\Utility\Bytes;
 use Drupal\Component\Utility\Crypt;
+
+require_once \Drupal::root() . '/core/includes/install.inc';
 use Drupal\Component\Utility\Environment;

We kozen bewust voor Drupal::root() in plaats van de klassieke DRUPAL_ROOT constante. Niet alleen omdat het nieuwer is, maar ook omdat we graag doen alsof we modern zijn.

Oplossing 2: op jacht naar null

Met de statuspagina weer werkend, stuitten we op een nieuwe foutmelding:
"Media: The source plugin for the media type is missing."

Na een korte zijmissie in media.type.document.yml bleek het label van het mediatype null te zijn. En jawel, dát label werd doorgegeven aan Html::escape(), die daar terecht chagrijnig van werd.

Oplossing 3: het mediatype fatsoeneren

De fix bleek eenvoudig:

drush cset media.type.document label "Document" -y

Maar de oorzaak zat dieper. Onze eigen blog-receptmodule had in de configuratie name: Document gezet, waar label: Document hoorde te staan. Aangepast, opgeslagen, vergeten.

Bonus: mooie url's zijn gratis reclame

Omdat we toch in configuratiestand stonden: waarom zouden blogposts nog node/123-achtige URLs hebben? We wilden iets vriendelijkers en Nederlandser. Zoals:

/praatje/de-titel-van-het-bericht

Met een eenvoudig Pathauto-patroon ingesteld via code is dat nu standaard voor al onze blogposts.

Lessen geleerd

  • patches zijn je vrienden
    Gebruik composer-patches om core-fixes netjes te beheren, vooral als je weet dat de upstream fix nog even op zich laat wachten.
  • oorzaak > symptoom
    Een null patchen voorkomt misschien een crash, maar lost niets op. Zoek verder.
  • let op bij recepten
Tags

More Blog Posts