Een automatische WordPress-update is mislukt: zo herstel je veilig

WordPress mailde dat de automatische update niet is voltooid. Misschien is je site prima, misschien hangt hij in onderhoudsmodus, of misschien draait hij de nieuwe versie met gecachete oude code. Dit artikel loopt het veilige herstelpad af: controleer eerst de staat van de site, ruim het .maintenance-bestand op, werk de vijf echte oorzaken door en bevestig daarna of de update echt is afgerond.

Je opent je inbox en ziet een mail met de onderwerpregel "[je sitenaam] An automated WordPress update has failed to complete - please attend to the issues", of een vergelijkbare melding in wp-admin. Het bericht is best ongemakkelijk. Het zegt niet of je site nog draait, wat bezoekers zien, of waar je moet beginnen. De eerlijke eerste stap is uitzoeken wat er nu écht stuk is, en de eerlijke tweede stap is het juiste probleem in de juiste volgorde herstellen. Dit artikel loopt allebei door.

Wat de mail of admin-melding eigenlijk betekent

WordPress stuurde die mail via de auto_core_update_email hook, die er al sinds WordPress 3.7 (uit 2013) in zit. Het type achter jouw mail is een van drie: success (de update werkte), fail (een niet-kritieke stap ging mis voordat de bestanden gekopieerd werden, vaak een download-probleem) of critical (een ernstige fout tijdens het kopiëren, zoals een volle schijf of een mislukte rollback). Het zijn de typen fail en critical die de "failed to complete"-onderwerpregel produceren.

Een fail herstel je doorgaans met een retry. Een critical niet. WordPress zet dan een interne vlag en stopt met automatische update-pogingen totdat jij ingrijpt. De gedachte daarachter: een kritieke fout suggereert dat de site in een staat zit waar nóg een poging dingen alleen maar erger maakt.

Eerst even checken: draait je site überhaupt?

Voordat je iets aanpast, kijk je gewoon wat bezoekers nu zien. De mail vertelt het je niet. Sommige fouten laten je site doodleuk op de oude versie staan. Andere zetten 'm vast in onderhoudsmodus. Open je homepage in een privé-browservenster en let op drie dingen.

  • De pagina laadt normaal. De update is afgebroken voordat er iets stuk kon. De site draait op de oude versie. Het herstel is rustig en je hebt tijd.
  • De pagina toont "Briefly unavailable for scheduled maintenance. Check back in a minute." Er is een .maintenance-bestand achtergebleven in de WordPress-root. Bezoekers krijgen een 503. Dat heeft de directe fix hieronder nodig. De volledige uitleg staat in briefly unavailable for scheduled maintenance: een vastgelopen WordPress-update oplossen.
  • De pagina toont "Er heeft zich een kritieke fout voorgedaan op deze site". De update heeft de bestanden wel vervangen, maar de code is nu kapot. Behandel de mail dan als bijzaak en volg eerst there has been a critical error on this website.

Open wp-admin in een apart tabblad. Lukt dat, log in en ga naar Dashboard > Updates. WordPress laat zien of de update echt nog open staat of dat hij stilletjes is afgerond zonder dat de mail-handler dat door had. Het versienummer onderin elke admin-pagina is de bron van waarheid voor welke versie er nu echt draait.

De meest voorkomende oorzaken, op volgorde van waarschijnlijkheid

Na een hoop van dit soort incidenten is de volgorde redelijk constant.

  1. Onvoldoende schijfruimte, vaak in wp-content/upgrade-temp-backup/. WordPress 6.3 introduceerde deze map zodat het mislukte handmatige plugin- en thema-updates kan terugdraaien door de oude versie met move_dir() te verplaatsen. Een wekelijkse WP-Cron-taak ruimt 'm op, maar op een krap pakket of bij veel updates loopt de schijf vol vóór die cron langskomt. WordPress stuurt dan een critical-mail omdat het nieuwe pakket niet meer uitgepakt kan worden.
  2. Bestandsrechten blokkeren directe updates. WordPress kiest zijn schrijfmethode via get_filesystem_method(). De volgorde is direct, dan ssh2, dan ftpext, dan ftpsockets. Bezit de PHP-gebruiker de WordPress-bestanden niet? Dan valt direct af en stapt WordPress over op een methode die credentials nodig heeft die hij tijdens een automatische update niet heeft. De update breekt af voordat er één bestand is aangeraakt.
  3. PHP-timeout of out-of-memory midden in de update. Shared-hosting-pakketten met een strakke max_execution_time (vaak 30 tot 60 seconden) of een lage memory_limit (vaak 128M) kunnen het PHP-proces afkappen terwijl het nog een release-zip aan het uitpakken is of een database-upgrade draait. De update is dan half klaar en je krijgt een mail.
  4. Netwerkfout tijdens de download van het pakket. De download van downloads.wordpress.org liep stuk, je host blokkeerde de uitgaande verbinding, of de integriteitscheck wees de bytes af. WordPress detecteerde dat en brak af voordat hij iets toepaste. Dit is een fail, geen critical, en lukt meestal bij de volgende cron-tick wel.
  5. OPcache serveert oude bytecode na de update. De bestanden zijn netjes vervangen, maar de OPcache van PHP heeft de oude bytecode nog in het geheugen. De site laadt, maar draait een mix van oude en nieuwe code, en dat is instabiel. WordPress probeert OPcache te invalideren via wp_opcache_invalidate() (sinds WordPress 5.5) en wp_opcache_invalidate_directory() (sinds WordPress 6.2), maar op hosts waar de PHP-pool van de cron een andere is dan die van de webrequests, vinden die calls niet de juiste cache.

Met de diagnose hieronder weet je welke oorzaak speelt voordat je iets aanraakt.

Eerst diagnosticeren, dan pas fixen

Je wil signaal, geen ruis. Loop deze checks op volgorde af. Stop bij de eerste die een duidelijk antwoord geeft.

Check 1: staat de site in onderhoudsmodus? Open in de file manager van je hostingpaneel (cPanel, DirectAdmin, Plesk of een vergelijkbare) de WordPress-root, de map waarin wp-config.php staat. Zet Show Hidden Files aan in de instellingen. Staat er een bestand .maintenance? Dan hangt de site vast. De fix vind je hieronder.

Check 2: hoe vol is de schijf? Zoek in je hostingpaneel het overzicht van de schijfruimte (cPanel: Statistics > Disk Usage, DirectAdmin: Disk Usage, Plesk: Hosting Services > [domein] > Statistics). Zit je op 95% of hoger? Dat is je oorzaak. Kijk daarna specifiek naar wp-content/upgrade-temp-backup/: open die map in de file manager en check of er nog oude plugins/- of themes/-submappen in staan van eerdere mislukte updates. Site Health in wp-admin heeft een test voor deze tijdelijke backup-directory die hier op aanslaat.

Check 3: wat zegt de WordPress debug log? Staat WP_DEBUG_LOG aan (in wp-config.php)? Open dan wp-content/debug.log via de file manager. De laatste regels van het tijdstip van de update vertellen precies wat er stuk ging. Een regel als Failed to copy ... wijst op rechten of schijfruimte. Een regel als Maximum execution time of 30 seconds exceeded wijst op de PHP-timeout. Staat WP_DEBUG_LOG nog niet aan? Zie dan de WordPress debug log inschakelen en lezen om dat veilig in te stellen.

Check 4: wat zegt de error log van je host? Elk modern hostingpaneel heeft een PHP error log voor je site. cPanel noemt dat Errors, DirectAdmin Error Log, Plesk Logs. Zoek de regels rond het tijdstip van de update. PHP-fatals, segfaults en out of memory-killers verschijnen hier ook als de WordPress debug log stilzwijgt.

Check 5: meldt Site Health iets? Open Tools > Site Health in wp-admin. Het tabblad Status test de schrijfbaarheid van de tijdelijke backup-map, het loopback-request en de cron-gezondheid. Elke gefaalde test is extra signaal.

Nu weet je met welke oorzaak je te maken hebt. Door naar de bijbehorende fix.

De directe fix: verwijder het .maintenance-bestand

Toont je site de onderhoudsmelding? Pak dat dan eerst aan, vóór alles. Bezoekers krijgen een 503 en het maakt ze niet uit waarom.

  1. Ga in de file manager van je hostingpaneel naar de WordPress-root (de map waarin wp-config.php staat).
  2. Zet Show Hidden Files aan als je dat nog niet hebt gedaan.
  3. Klik met rechts op .maintenance en kies Verwijderen. Bevestig.
  4. Herlaad je homepage in een privé-browservenster.

Je weet dat het werkte als de homepage normaal laadt, of als hij een ándere foutmelding toont. Een andere melding is goed nieuws: het onderhoudsmasker is weg en je kan nu het echte probleem eronder zien en aanpakken.

De volledige diagnostische context voor dit bestand staat in briefly unavailable for scheduled maintenance: een vastgelopen WordPress-update oplossen. Komt .maintenance binnen seconden weer terug? Dan loopt er een geplande auto-update die telkens opnieuw faalt, en zit het antwoord verderop in de oorzaak-secties.

Oorzaak A: te weinig schijfruimte (upgrade-temp-backup vol)

Dit is verreweg de meest voorkomende kritieke fout op kleinere pakketten. Oude failed-update backups in wp-content/upgrade-temp-backup/plugins/ en wp-content/upgrade-temp-backup/themes/ stapelen zich op, de schijf heeft geen lucht meer voor de nieuwe release-zip, en de unpack-stap loopt halverwege stuk.

Los het in drie stappen op.

  1. Maak eerst ruimte vrij. Ga in je file manager naar wp-content/upgrade-temp-backup/. Leeg zowel de map plugins/ als themes/. De wekelijkse WP-Cron-taak die dit normaal doet, deed het overduidelijk niet, dus doe je het nu zelf. Leeg ook wp-content/upgrade/ als daar oude troep in staat.
  2. Controleer of er nu genoeg ruimte vrij is. Vuistregel: voor een core-update wil je minstens de huidige WordPress-installatie plus 200 MB vrij hebben. Op een 5 GB pakket betekent dat onder 4,5 GB blijven.
  3. Probeer de update opnieuw. Ga in wp-admin naar Dashboard > Updates en klik Update Now. Of wacht op de volgende WP-Cron-tick als het een automatische update was.

Je weet dat het werkte als de Updates-pagina het nieuwe versienummer toont en je homepage laadt met de nieuwe WordPress-versie zichtbaar in de footer van het dashboard.

Loop je telkens vol? Dan is het pakket zelf de echte oorzaak. Een WordPress core-update wil ongeveer 60 tot 80 MB werkruimte, een grote plugin-update vaak veel meer. Als je pakket je geen lucht geeft, raak je dit elke release-cyclus weer.

Oorzaak B: bestandsrechten blokkeren directe updates

get_filesystem_method() heeft de direct-methode afgewezen omdat het PHP-proces en de WordPress-bestanden van verschillende eigenaren zijn. Een typisch teken in de error log van je host is een regel als "Could not create directory" of "failed to open stream: Permission denied". Bezoekers zien soms zelfs het FTP-credentials-formulier in WordPress als jij vanuit het dashboard handmatig op update klikt.

De volledige uitleg en fix staat in WordPress vraagt om FTP-gegevens bij plugin-installatie. De korte versie voor dit scenario:

  • Op de meeste managed en shared hosts los je dit op in het hostingpaneel, niet in wp-config.php. cPanel: File Manager > Permissions of even support mailen om de eigenaar gelijk te trekken. Plesk: Hosting & DNS > Hosting Settings voor de FTP-gebruiker, of de Permissions Recalculation tooling. DirectAdmin: open de gebruikersinstellingen en check de PHP-uitvoermethode.
  • Heb je shell-toegang? Dan zet chown -R www-data:www-data /var/www/jouwsite.nl/public (pas het aan naar je PHP-gebruiker en pad) de eigenaar van de bestanden gelijk aan het PHP-proces. Daarna wordt direct gekozen en lopen updates zonder gevraag.
  • De kortere weg in wp-config.php is define( 'FS_METHOD', 'direct' );, maar zet dat alleen aan nadat je hebt bevestigd dat de PHP-gebruiker echt kan schrijven. Dit zonder de eigenaar fixen verandert het vriendelijke prompt in een stille fout.

Je weet dat het werkte als de volgende handmatige update vanuit je dashboard de install-progressie toont zonder FTP-formulier, en de mail niet meer komt.

Oorzaak C: PHP-timeout of out-of-memory tijdens de update

De update loopt, het pakket wordt uitgepakt, en PHP wordt afgekapt voordat hij klaar is. WordPress mailt je omdat de afrondingsstappen niet meer afkomen. De site is dan misschien half geüpdatet.

Zoek in de error log van je hostingpaneel naar één van deze handtekeningen:

  • PHP Fatal error: Maximum execution time of N seconds exceeded
  • PHP Fatal error: Allowed memory size of N bytes exhausted
  • Het PHP-proces is OOM-killed (de regel staat dan niet altijd in de PHP-log; op Linux-hosts staat 'ie in de system journal).

Hoe je deze limieten ophoogt, hangt af van je paneel.

  • cPanel: open MultiPHP INI Editor, schakel naar Editor Mode en zet max_execution_time op 300 en memory_limit op 512M voor je domein.
  • DirectAdmin: onder Domain Setup > [je domein] > PHP Settings vind je dezelfde twee waardes.
  • Plesk: Websites & Domains > [je domein] > PHP Settings, pas memory_limit en max_execution_time aan.
  • Geen GUI-toegang: bewerk wp-config.php en voeg define( 'WP_MEMORY_LIMIT', '512M' ); toe voor het geheugen. De execution time-cap moet meestal op serverniveau opgehoogd worden, maar set_time_limit( 300 ); bovenin wp-config.php werkt op hosts die het toelaten.

Je weet dat het werkte als de volgende update zonder mail klaarkomt, de footer in het dashboard de nieuwe versie toont, en Tools > Site Health geen oranje of rode vlaggen heeft. Houdt je host je vast onder 60 seconden en wil hij niet meebewegen? Dan is dat een signaal om eens naar een ander pakket te kijken. De volle context staat in allowed memory size exhausted in WordPress en maximum execution time exceeded in WordPress.

Oorzaak D: netwerkfout tijdens de download van het pakket

De download van downloads.wordpress.org was incompleet of de integriteitscheck verwierp de bytes. WordPress brak af voordat hij iets aanraakte. Dit is een fail, geen critical, en de meest onschuldige oorzaak.

Diagnose is kort. Zoek in de error log van je hostingpaneel naar regels als "Could not write file" in de buurt van een download-URL, of DNS-fouten met downloads.wordpress.org. Op het scherm Tools > Site Health slaat de Loopback-test of de HTTP requests-test soms aan op de onderliggende beperking.

De fix is bijna altijd: opnieuw proberen. WP-Cron probeert de update bij de volgende tick weer en de meeste van deze fouten lossen zichzelf op bij de tweede poging, omdat de netwerkglitch tijdelijk was.

Blijven retries falen? Dan blokkeert de host uitgaande HTTPS of zit er iets mis met DNS richting WordPress.org. Open een ticket bij je host en vraag of PHP op jouw account https://api.wordpress.org/ en https://downloads.wordpress.org/ kan bereiken. Verwachte uitkomst: beide endpoints geven HTTP 200 vanaf de server.

Je weet dat het werkte als de volgende mail het success-type is, of als de Updates-pagina na de cron-tick de nieuwe versie toont.

Oorzaak E: OPcache serveert oude bytecode na de update

De bestanden zijn netjes geüpdatet. De footer in wp-admin toont de nieuwe versie. Maar aan de voorkant verschijnen rare fouten: undefined functions, ontbrekende methods, fatals op pagina's die net nog werkten. De site draait de nieuwe code in sommige stukken en de oude bytecode in andere, omdat OPcache de file changes niet heeft gezien.

Dit is zeldzaam op standaard hosting, maar komt voor in twee situaties:

  • Het PHP-proces dat WP-Cron draait is een andere FPM-pool dan de pool die webrequests serveert. WordPress riep wp_opcache_invalidate() aan in de cron-worker, die invalideerde alleen de OPcache van de cron, en de webpool houdt de oude bytecode vast.
  • opcache.validate_timestamps staat op 0 voor performance, wat PHP vertelt nooit te checken of het bronbestand veranderd is. Voor productie is dat goed, maar het betekent ook dat OPcache alleen ververst als de pool herstart.

De fix is: OPcache flushen op de juiste pool.

  • cPanel of DirectAdmin: open Select PHP Version (of MultiPHP Manager) en klik Restart PHP als die optie er staat. Sommige hosts hebben ook een aparte OPcache Reset knop.
  • Plesk: Websites & Domains > [je domein] > PHP Settings, en bewaar zonder iets te wijzigen. Plesk herstart de FPM-pool bij elke save, en dat flusht OPcache.
  • Geen GUI-optie: zet een bestand opcache-reset.php in de WordPress-root met precies <?php if ( function_exists( 'opcache_reset' ) ) { opcache_reset(); echo 'flushed'; }, laad het één keer in je browser en gooi het meteen weer weg. Het laten staan is een security-risico.

Je weet dat het werkte als de fouten aan de voorkant verdwijnen, het dashboard zonder notices laadt, en php -i | grep opcache (als je shell-toegang hebt) bevestigt dat opcache_reset() is gedraaid.

Controleer of de update echt is afgerond

Heb je de juiste fix toegepast? Bevestig dan drie dingen voordat je het incident dichtklapt.

  • Het versienummer klopt. In wp-admin toont elke pagina-footer de actieve WordPress-versie. Vergelijk hem met de versie uit de mislukte-update mail. Die horen gelijk te zijn.
  • De voorkant laadt vanuit een privé-venster. Ingelogde views kunnen misleidend zijn door admin-only-gedrag. Een privé-venster toont wat bezoekers echt zien.
  • Site Health is groen. Tools > Site Health > Status. De test op de schrijfbare backup-directory, de loopback-test en de cron-test horen alle drie groen te zijn. Een oranje vlag is een hint dat de oorzaak nog niet helemaal weg is.

Slagen alle drie? Dan is de update klaar. Komt de mail bij de volgende cron-tick weer? Dan zit de echte oorzaak nog ergens, en ga je terug naar de diagnose.

Wanneer je hulp inschakelt

Heb je de diagnose en de bijbehorende fix doorlopen en draait de site nog steeds niet op de nieuwe versie, of blijft de mail komen? Leg het probleem dan neer bij je host of een WordPress-specialist met een kant-en-klaar pakket. Het eerste uur van elk incident is context verzamelen, en dat kun je hen besparen.

Verzamel voordat je vraagt:

  • De exacte tekst van de failed-update mail, inclusief de WordPress-versie die hij probeerde te installeren.
  • Je huidige WordPress-versie (uit de footer van een willekeurige wp-admin-pagina).
  • De PHP-versie (uit je hostingpaneel onder PHP-instellingen).
  • De vrije schijfruimte op dit moment, en specifiek de grootte van wp-content/upgrade-temp-backup/ als die map bestaat.
  • De laatste 50 regels uit wp-content/debug.log van het tijdstip van de update.
  • De laatste 50 regels uit de error log van het hostingpaneel voor hetzelfde venster.
  • Het pakket-niveau van je hosting en eventuele quotums of limieten die het paneel toont (memory, execution time, schijf).
  • Een lijstje van alle diagnostische checks en fixes die je al hebt geprobeerd, op volgorde, en wat er telkens veranderde.
  • Of je homepage nu laadt, of wp-admin nu laadt, en wat ze allebei tonen in een privé-browservenster.

Een specialist prikt er met dat pakket meestal in 20 tot 30 minuten doorheen. Zonder pakket duurt dezelfde klus de rest van de middag.

Hoe je deze situatie voortaan minder waarschijnlijk maakt

Tijdelijke fouten kun je niet helemaal voorkomen, maar het herstel kun je wel saai maken in plaats van stressvol.

  • Houd minstens 500 MB vrije schijfruimte aan. Dat voorkomt de meest voorkomende critical-mail en de stille corruptie die ermee komt. Laat je pakket dat niet toe? Dan is het pakket zelf het probleem.
  • Plan een wekelijkse opruiming van wp-content/upgrade-temp-backup/. WordPress probeert dit zelf, maar slechts wekelijks en alleen als WP-Cron gezond is. Eens per maand even Tools > Site Health checken is genoeg.
  • Test je backups voordat je ze nodig hebt. Een backup die nog nooit teruggezet is, is geen backup. Eén keer een proefrestore op een staging-kopie maakt van het herstelpad theorie iets wat in je vingers zit. De volle uitleg staat in een WordPress-site herstellen vanaf een backup.
  • Houd het admin-mailadres op een inbox die je echt leest. De mail uit dit artikel is je vroegste waarschuwing, en die is waardeloos als hij ergens belandt waar je niet kijkt.
  • Update tijdens rustige uren. Elk incident herstel je makkelijker als niemand op dat moment de winkelmand aan het vullen, een formulier aan het versturen of de contactpagina aan het laden is. Met de auto_update_core_dev en gerelateerde filters stuur je het updatevenster zelf, of laat je het over aan een managed host die updates voor je inplant.
  • Voor missiekritische sites: maak vlak voor een geplande auto-update een backup. De meeste managed hosting-platformen kunnen het uur vóór de geplande core- of plugin-updates een backup afvuren. Doet de jouwe dat niet? Plan er dan zelf een in.

De "automated update has failed to complete" mail is vervelend, maar de faalmodes zijn beperkt en de fixes zijn ingesleten. De eerlijke versie is dat het meeste van dit type incident neerkomt op schijfruimte, bestandsrechten of PHP-limieten, en uitvinden welke speelt is de helft van het werk.

Wil je dat dit niet steeds jouw probleem is?

Als storingen blijven terugkomen, is de 'fix' vaak consistent beheer: updates, backups en monitoring die niet versloffen.

Bekijk WordPress onderhoud

Doorzoek deze site

Begin met typen om te zoeken, of blader door de kennisbank en blog.