L’erreur 500 de WordPress est l’équivalent web du témoin « vérifiez le moteur » de votre voiture—sauf que le tableau de bord est une page blanche et que votre responsable regarde les analytics chuter en temps réel.
Le pire n’est pas l’erreur. C’est l’imprécision. « Internal Server Error » signifie essentiellement que le serveur hausse les épaules.
Ce guide est ce qu’il faut faire quand vous devez remettre le site en ligne immédiatement et que vous voulez éviter la traditionnelle « réparation » consistant à désactiver au hasard des éléments jusqu’à ce que ça marche.
Nous serons chirurgicaux : confirmer où le 500 est généré, lire les bons logs, isoler la couche (edge → serveur web → runtime PHP → WordPress), et livrer un correctif avec plan de retour arrière.
Ce que signifie réellement une erreur 500 WordPress (et ce que ça n’est pas)
Un code 500 signifie que le serveur n’a pas pu satisfaire une requête à cause d’une condition inattendue. Ce n’est pas que la requête était mal formée (c’est 400/404),
et ce n’est pas que vous êtes limité par taux (429) ou que votre upstream est défaillant (502/504). Un 500 est généralement généré par le serveur d’origine ou le runtime applicatif.
Dans l’écosystème WordPress, « 500 Internal Server Error » correspond souvent à :
- Erreurs de configuration du serveur web (mauvaises règles de réécriture, directives invalides, modules manquants).
- Crashs du runtime PHP ou erreurs fatales (exceptions non interceptées, fonctions indéfinies, épuisement mémoire).
- Problèmes de pool PHP-FPM (max children atteint, timeouts slowlog, permissions des sockets).
- Problèmes de permission/propriété du système de fichiers (impossibilité de lire plugins/themes, impossibilité d’écrire cache/temp).
- Contraintes de ressources (CPU saturé, disque plein, épuisement d’inodes).
- Règles de sécurité/WAF qui font remonter des 500 génériques depuis l’upstream.
Aussi, n’oubliez pas que « 500 WordPress » n’est parfois pas WordPress. Ça peut être le CDN qui renvoie un 500 générique parce que l’origine a renvoyé autre chose,
ou parce que l’edge ne peut pas atteindre l’origine proprement. Vérifiez toujours où le code d’état est créé.
Une citation à garder dans votre checklist mentale d’incident vient de Werner Vogels (CTO Amazon) : « Everything fails, all the time. » Ce n’est pas du pessimisme ; c’est de la planification.
Playbook de diagnostic rapide (vérifications première/seconde/troisième)
Étape 0 : Arrêtez de deviner. Confirmez la couche en panne.
Avant de toucher à WordPress, déterminez si le 500 provient de l’edge (CDN/WAF), du serveur web (Nginx/Apache) ou de PHP (PHP-FPM/mod_php).
Votre premier gain est de réduire le périmètre d’investigation.
Première vérification (2 minutes) : reproduire et capturer les en-têtes de réponse
- Si les en-têtes montrent
server: cloudflareou similaire, validez s’il s’agit d’un 500 d’origine ou d’une erreur générée en edge. - Si vous voyez
X-Powered-By: PHPet un identifiant de requête fourni par votre plateforme, vous avez une piste à suivre.
Deuxième vérification (5 minutes) : lisez les bons logs, pas tous les logs
- Le fichier d’erreurs du serveur web pour l’horodatage et le chemin de la requête.
- Le log d’erreurs PHP-FPM (ou php_errors dans syslog/journald).
- Le log de débogage WordPress seulement s’il est activé—et de préférence activé temporairement.
Troisième vérification (10 minutes) : isolez WordPress de la plateforme
- Appelez un fichier statique (comme
/favicon.ico) pour vérifier si le serveur web peut servir quelque chose. - Appelez
/wp-login.phpet un endpoint phpinfo simple si vous en disposez (ou créez-en temporairement un sécurisé puis supprimez-le). - Désactivez les plugins et changez de thème (de manière sûre) si les logs pointent vers des fatales PHP ou des problèmes d’ordre de chargement de plugins.
Si vous effectuez ces trois vérifications avec rigueur, la plupart des incidents 500 passent de « mystérieux » à « actionnable » rapidement.
Si vous les sautez, vous ferez ce que font les humains sous stress : changer cinq choses et ne rien apprendre.
Causes les plus fréquentes (par couche)
1) CDN/WAF et reverse proxies : des erreurs d’origine déguisées
Un CDN peut transmettre fidèlement un 500 d’origine, ou émettre son propre 500 s’il ne peut pas atteindre l’origine, s’il ne peut pas négocier TLS, ou s’il reçoit une réponse invalide.
Certains WAF gérés bloquent aussi des requêtes et renvoient une page d’erreur brandée qui ressemble à un « 500 » pour les utilisateurs.
Votre travail : vérifiez si l’origine renvoie bien un 500 lorsqu’on y accède directement (en contournant le CDN), et si la requête n’est pas réécrite de façon surprenante.
2) Nginx/Apache : règles de réécriture, permissions et mauvais routages
WordPress dépend fortement des réécritures. Une seule directive incorrecte peut se transformer en 500. Il en va de même pour une ligne invalide dans .htaccess, ou une config Nginx faisant référence à un fichier manquant.
Sous Apache, un 500 survient aussi quand le serveur rencontre une directive qu’il ne comprend pas (souvent après un changement de module).
3) Runtime PHP : erreurs fatales, mémoire et versions incompatibles
La plupart des 500 WordPress réels sont des fatales PHP. Une mise à jour de plugin appelle une fonction inexistante dans votre version de PHP. Un thème suppose qu’une extension est installée.
Une fuite mémoire se transforme en « Allowed memory size exhausted » et le runtime s’arrête en plein milieu de la requête.
Un autre coupable fréquent est l’OPcache après un déploiement. OPcache est excellent—jusqu’à ce qu’il ne le soit plus. Le vider peut faire la différence entre stable et hanté.
4) PHP-FPM : pools sous pression
Quand PHP-FPM atteint pm.max_children, les requêtes s’alignent. Selon les timeouts du serveur web, cela se traduit souvent par des 502/504, mais ça peut aussi apparaître en 500
si la configuration de l’upstream est incorrecte ou si l’application renvoie une sortie partielle. Également : les permissions du socket et les contraintes chroot/open_basedir peuvent produire des échecs ressemblant à des erreurs applicatives.
5) Système de fichiers et stockage : disque plein, épuisement d’inodes et dérive des permissions
WordPress écrit. Il écrit des fichiers de cache, des uploads, des mises à jour de plugins, des fichiers temporaires, des sessions, parfois des logs. Si le disque est plein, vous pouvez obtenir des erreurs étonnamment génériques.
Si le nombre d’inodes est épuisé, vous pouvez avoir des gigaoctets libres et être malgré tout « plein ».
La dérive des permissions est plus courante qu’on ne l’admet : une édition manuelle en root, un déploiement qui change la propriété, une étape de durcissement qui empêche l’utilisateur PHP de lire un fichier de plugin.
La pile web répond par—vous l’avez deviné—un 500.
6) Base de données et dépendances externes : les erreurs remontent mal
Les pannes purement liées à la base de données montrent souvent « Error establishing a database connection », mais selon la gestion des erreurs et les couches de cache d’objets,
les exceptions DB peuvent être avalées et relancées sous forme de 500 génériques. Redis/Memcached mal configurés peuvent produire le même effet.
Blague #1 : Une erreur 500 est la façon pour le serveur de dire « J’ai des sentiments aussi », et en ce moment ils sont surtout paniqués.
Tâches pratiques avec commandes, sorties et décisions
Ce sont des tâches de qualité production. Elles supposent Linux, Nginx ou Apache, et PHP-FPM. Ajustez les chemins selon votre distribution.
Chaque tâche inclut (a) une commande, (b) ce que signifie la sortie typique, et (c) la décision à prendre ensuite.
Task 1: Capture the failing response and confirm where the 500 is generated
cr0x@server:~$ curl -sS -D- -o /dev/null https://example.com/ | sed -n '1,20p'
HTTP/2 500
date: Fri, 26 Dec 2025 18:42:10 GMT
content-type: text/html; charset=UTF-8
server: nginx
x-request-id: 7f2c9a4e9b0f3c1a
Ce que ça signifie : La réponse vient de nginx (pas d’un CDN). L’identifiant de requête est de l’or si vos logs l’incluent.
Décision : Allez directement aux logs d’erreurs Nginx et aux logs PHP-FPM pour cet horodatage/identifiant.
Task 2: Bypass the CDN and hit origin directly (if possible)
cr0x@server:~$ curl -sS -D- -o /dev/null -H "Host: example.com" http://203.0.113.10/ | sed -n '1,20p'
HTTP/1.1 500 Internal Server Error
Server: nginx
Date: Fri, 26 Dec 2025 18:42:13 GMT
Content-Type: text/html
Ce que ça signifie : L’origine renvoie aussi 500. Ce n’est pas « le CDN qui fait des siennes ».
Décision : Déboguez la pile d’origine. Si l’origine renvoie 200 mais que le CDN renvoie 500, examinez les règles de l’edge, TLS, WAF ou les checks de santé de l’origine.
Task 3: Watch the web server error log live while reproducing
cr0x@server:~$ sudo tail -n 50 -f /var/log/nginx/error.log
2025/12/26 18:42:10 [error] 1129#1129: *928 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught Error: Call to undefined function mb_strlen() in /var/www/html/wp-includes/formatting.php:1234" while reading response header from upstream, client: 198.51.100.23, server: example.com, request: "GET / HTTP/2.0", upstream: "fastcgi://unix:/run/php/php8.1-fpm.sock:", host: "example.com"
Ce que ça signifie : Cause racine claire : fatal PHP dû à l’extension mbstring manquante.
Décision : Installez/activez l’extension manquante, rechargez PHP-FPM, et retestez. Ne touchez pas encore aux plugins WordPress ; la pile vous indique exactement le problème.
Task 4: Check PHP-FPM service health and recent errors
cr0x@server:~$ sudo systemctl status php8.1-fpm --no-pager -l
● php8.1-fpm.service - The PHP 8.1 FastCGI Process Manager
Loaded: loaded (/lib/systemd/system/php8.1-fpm.service; enabled)
Active: active (running) since Fri 2025-12-26 17:01:22 UTC; 1h 40min ago
Main PID: 901 (php-fpm8.1)
Status: "Processes active: 12, idle: 4, Requests: 28291, slow: 7, Traffic: 0.0req/sec"
...
Ce que ça signifie : Le service est actif. « slow: 7 » indique des requêtes lentes mais pas nécessairement la cause du 500.
Décision : Si les erreurs ne sont pas évidentes dans les logs web, inspectez les logs PHP-FPM et envisagez d’activer temporairement le slowlog.
Task 5: Inspect PHP-FPM error log for fatal errors or pool saturation
cr0x@server:~$ sudo tail -n 80 /var/log/php8.1-fpm.log
[26-Dec-2025 18:42:10] WARNING: [pool www] child 2134 said into stderr: "PHP Fatal error: Uncaught Error: Call to undefined function mb_strlen() in /var/www/html/wp-includes/formatting.php:1234"
[26-Dec-2025 18:40:55] WARNING: [pool www] server reached pm.max_children setting (20), consider raising it
Ce que ça signifie : Deux problèmes : extension manquante (500 immédiats) et saturation du pool (risque de performance).
Décision : Corrigez la fatale d’abord (restauration du service), puis abordez la capacité : augmentez pm.max_children seulement après avoir confirmé la marge mémoire.
Task 6: Confirm PHP extensions and version align with what WordPress expects
cr0x@server:~$ php -v
PHP 8.1.26 (cli) (built: Nov 21 2025 10:12:33) (NTS)
cr0x@server:~$ php -m | egrep -i 'mbstring|mysqli|curl|gd|imagick|zip|openssl' || true
curl
mysqli
openssl
zip
Ce que ça signifie : Pas de mbstring. Le cœur WordPress et de nombreux plugins l’attendent.
Décision : Installez le paquet php-mbstring pour votre distro, redémarrez PHP-FPM, retestez. Si le CLI diffère du FPM, vérifiez le chemin ini du FPM.
Task 7: Validate web server config syntax (cheap, fast, often overlooked)
cr0x@server:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Ce que ça signifie : La config Nginx est correcte en syntaxe.
Décision : Si vous obtenez des erreurs ici, corrigez-les avant toute autre chose. Aucun débogage WordPress ne sera utile quand le serveur web ne charge pas correctement les règles.
Task 8: For Apache, check config and .htaccess fallout
cr0x@server:~$ sudo apachectl configtest
Syntax OK
Ce que ça signifie : La configuration Apache de base est OK. Cela ne garantit pas que .htaccess ne casse pas les requêtes.
Décision : Déplacez temporairement .htaccess si vous suspectez des problèmes de réécriture, puis retestez.
Task 9: Quarantine .htaccess to rule out bad directives
cr0x@server:~$ cd /var/www/html
cr0x@server:~$ sudo mv .htaccess .htaccess.bak.$(date +%s)
cr0x@server:~$ sudo -u www-data php -l index.php
No syntax errors detected in index.php
Ce que ça signifie : Si le site revient après avoir déplacé .htaccess, vos règles de réécriture ou directives étaient invalides.
Décision : Recréez les permaliens depuis l’admin WordPress une fois stable, ou reconstruisez les règles minimales standard WordPress et réintroduisez les changements progressivement.
Task 10: Disable plugins safely without wp-admin (rename directory)
cr0x@server:~$ cd /var/www/html/wp-content
cr0x@server:~$ sudo mv plugins plugins.disabled.$(date +%s)
cr0x@server:~$ ls -1
mu-plugins
plugins.disabled.1766774712
themes
uploads
Ce que ça signifie : WordPress ne chargera pas les plugins normaux si le répertoire est absent/renommé. Il chargera toujours les mu-plugins.
Décision : Si le 500 disparaît, un plugin provoquait la fatale. Restaurer le répertoire, puis réactiver les plugins par lots ou un par un pour identifier le coupable.
Task 11: Switch to a default theme (when theme code is suspect)
cr0x@server:~$ cd /var/www/html/wp-content/themes
cr0x@server:~$ sudo mv mytheme mytheme.disabled.$(date +%s)
cr0x@server:~$ ls -1
mytheme.disabled.1766774766
twentytwentyfour
twentytwentythree
Ce que ça signifie : Si le thème actif est manquant, WordPress se rabattra sur un thème par défaut installé.
Décision : Si cela corrige le 500, le thème est cassé ou incompatible. Restaurez le déploiement du thème ou corrigez la fatale.
Task 12: Turn on WordPress debug logging (temporarily and responsibly)
cr0x@server:~$ sudo cp -a /var/www/html/wp-config.php /var/www/html/wp-config.php.bak.$(date +%s)
cr0x@server:~$ sudo grep -n "WP_DEBUG" /var/www/html/wp-config.php || true
cr0x@server:~$ sudo sed -i "s/\/\* That's all, stop editing! Happy publishing. \*\//define('WP_DEBUG', true);\ndefine('WP_DEBUG_LOG', true);\ndefine('WP_DEBUG_DISPLAY', false);\n\n\/\* That's all, stop editing! Happy publishing. \*\//" /var/www/html/wp-config.php
cr0x@server:~$ sudo -u www-data tail -n 30 /var/www/html/wp-content/debug.log
[26-Dec-2025 18:45:03 UTC] PHP Fatal error: Uncaught Error: Class "WooCommerce" not found in /var/www/html/wp-content/themes/mytheme/functions.php:211
Ce que ça signifie : Le thème attend WooCommerce, mais les plugins sont désactivés ou WooCommerce n’a pas pu se charger.
Décision : Corrigez les dépendances (protégez le code avec class_exists), ou restaurez le plugin requis une fois stable. Aussi : désactivez le debug une fois fini ; les logs peuvent divulguer des informations internes.
Task 13: Check disk usage and inode exhaustion (storage problems love 500s)
cr0x@server:~$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 39G 200M 100% /
cr0x@server:~$ df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/vda1 2621440 2621401 39 100% /
Ce que ça signifie : Vous manquez d’espace et d’inodes. Les mises à jour WordPress, les écritures de cache, les fichiers de session—tout peut échouer de manière imprévisible.
Décision : Libérez de l’espace immédiatement (logs, anciennes releases, cache), puis corrigez la cause (rotation des logs, politique de cache, croissance des uploads, dimensionnement des partitions).
Task 14: Identify giant offenders quickly
cr0x@server:~$ sudo du -xhd1 /var | sort -h
120M /var/cache
1.4G /var/log
6.8G /var/lib
cr0x@server:~$ sudo ls -lhS /var/log | head
-rw-r----- 1 syslog adm 920M Dec 26 18:40 syslog
-rw-r----- 1 root adm 210M Dec 26 18:15 nginx-error.log
Ce que ça signifie : Les logs mangent le disque. Cela correspond souvent à une boucle d’erreur nouvelle (comme un plugin fatal qui spamme les logs).
Décision : Rotatez/tronquez les logs pour récupérer de l’espace, mais corrigez aussi la boucle sous-jacente. Sinon vous reviendrez ici dans une heure.
Task 15: Check file ownership and permissions in WordPress directories
cr0x@server:~$ sudo namei -l /var/www/html/wp-content
f: /var/www/html/wp-content
drwxr-xr-x root root /
drwxr-xr-x root root var
drwxr-xr-x root root www
drwxr-xr-x root root html
drwx------ root root wp-content
Ce que ça signifie : wp-content est en 700 possédé par root. PHP exécuté en tant que www-data ne peut pas lire/écrire. Attendez-vous à des 500 et comportements admin étranges.
Décision : Corrigez la propriété/permissions pour correspondre à votre modèle de déploiement (souvent lisible par www-data, writable limité pour uploads/cache).
Task 16: Validate PHP-FPM socket permissions and connectivity from Nginx
cr0x@server:~$ ls -l /run/php/php8.1-fpm.sock
srw-rw---- 1 www-data www-data 0 Dec 26 17:01 /run/php/php8.1-fpm.sock
cr0x@server:~$ sudo grep -R "fastcgi_pass" -n /etc/nginx/sites-enabled | head
/etc/nginx/sites-enabled/example.conf:42: fastcgi_pass unix:/run/php/php8.1-fpm.sock;
Ce que ça signifie : Le socket existe et correspond à la config. Si les permissions étaient incorrectes ou le chemin mal apparié, Nginx loggerait des erreurs de connexion upstream.
Décision : Si le chemin du socket diffère, alignez la config Nginx ou la directive listen de PHP-FPM, puis rechargez les services.
Task 17: Check for pool saturation and memory headroom before “just increasing max_children”
cr0x@server:~$ ps -o pid,rss,cmd -C php-fpm8.1 | head
PID RSS CMD
901 17800 php-fpm: master process (/etc/php/8.1/fpm/php-fpm.conf)
2134 145200 php-fpm: pool www
2135 152300 php-fpm: pool www
cr0x@server:~$ free -m
total used free shared buff/cache available
Mem: 2048 1530 85 40 432 260
Swap: 1024 950 74
Ce que ça signifie : Les workers occupent ~150Mo RSS chacun. Vous avez peu de mémoire disponible et vous swappez fortement.
Décision : Ne pas augmenter pm.max_children maintenant. Réduisez l’utilisation mémoire (plugins, réglages du cache d’objets), ajoutez de la RAM, ou scalez horizontalement.
Task 18: Find PHP fatal errors in journald (common on systemd-based distros)
cr0x@server:~$ sudo journalctl -u php8.1-fpm -S "10 minutes ago" --no-pager | tail -n 30
Dec 26 18:42:10 server php-fpm8.1[901]: PHP Fatal error: Uncaught Error: Call to undefined function mb_strlen() in /var/www/html/wp-includes/formatting.php:1234
Ce que ça signifie : Confirme une fatale runtime proche de l’heure de l’incident.
Décision : Corrigez la dépendance manquante ; si la fatale change après votre correction, continuez d’itérer—n’assumez pas qu’il n’y a qu’un seul problème.
Task 19: Test a single PHP file through the web server path
cr0x@server:~$ printf '%s\n' '/dev/null
cr0x@server:~$ curl -sS -D- http://127.0.0.1/health.php | sed -n '1,10p'
HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html; charset=UTF-8
OK
Ce que ça signifie : L’exécution PHP via la pile fonctionne. L’échec est donc probablement dans le chemin de code WordPress (plugins/thème/cœur) plutôt que la connectivité FPM.
Décision : Concentrez-vous sur WordPress et ses dépendances ; gardez l’endpoint de santé temporaire et supprimez-le après l’incident.
Task 20: Remove the temporary test endpoint (because future you deserves peace)
cr0x@server:~$ sudo rm -f /var/www/html/health.php
cr0x@server:~$ test ! -e /var/www/html/health.php && echo "removed"
removed
Ce que ça signifie : L’endpoint a été supprimé.
Décision : Si vous avez besoin de contrôles de santé permanents, implémentez-les correctement (chemin restreint, authentification et surveillance), pas comme un artefact d’incident qui traîne.
Trois mini-récits du monde corporate (pannes réalistes)
Mini-récit 1 : L’incident causé par une mauvaise hypothèse
Un site marketing faisait tourner WordPress derrière un CDN et un WAF géré. L’équipe a vu un pic de « 500 errors » dans le monitoring synthétique et a supposé, par réflexe, que WordPress avait planté.
Ils se sont rués dans wp-content, ont renommé des plugins, et ont même rollbacké un thème.
Rien n’a changé. L’erreur a persisté, têtue. Pendant ce temps, comme ils modifiaient l’origine pendant un trafic de pointe, ils ont introduit une dérive de permissions :
un rapide scp en root a déposé des fichiers possédés par root dans le répertoire des plugins. Le site s’est empiré. Ils avaient maintenant des 500 intermittents et des dysfonctionnements admin bizarres.
La cause racine était en amont : le fournisseur WAF avait poussé un nouveau jeu de règles traitant un paramètre de requête courant de leur tracking publicitaire comme suspect.
Le WAF renvoyait une page 500 générique (pas un 403), parce que « sécurité par ambiguïté » est apparemment encore une fonctionnalité produit.
La correction fut ennuyeuse : contourner le CDN/WAF pour confirmer l’état de l’origine, ajouter une exception pour le paramètre de tracking et affiner la règle. Puis annuler les changements inutiles faits sur l’origine.
La leçon : un 500 n’est pas une confession de WordPress. C’est un symptôme. Confirmez où il est généré avant d’ouvrir la boîte à outils chirurgicale.
Mini-récit 2 : L’optimisation qui s’est retournée contre eux
Une équipe plateforme voulait des pages plus rapides et moins de CPU. Ils ont activé un caching full-page agressif avec un plugin, plus un microcaching côté serveur dans Nginx.
Sur le papier : moins d’exécutions PHP, base de données plus heureuse, coût réduit. Et pendant une semaine, tout semblait parfait.
Puis est venue une campagne promotionnelle. Le trafic a explosé, et avec lui les tentatives de connexion (légitimes et autres). La config de cache a accidentellement mis en cache des réponses qui ne devaient jamais l’être :
des fragments de pages connectées et, pire, des boucles de redirection pour des utilisateurs avec certains cookies. Les sessions PHP sont devenues erratiques. Les clés de cache étaient incorrectes.
Sous contrainte, les workers PHP-FPM se sont bloqués. Les requêtes se sont accumulées. Le serveur web a commencé à renvoyer un mélange de 500 et 502 selon le timeout qui se déclenchait en premier.
Le plugin écrivait aussi d’immenses fichiers de cache dans un répertoire sur la partition racine. Le disque est passé à 100% et tout est devenu « internal server error », y compris des services non liés.
La correction n’a pas été « désactiver le cache pour toujours ». Il a fallu : contraindre le comportement du cache, définir des règles de contournement correctes pour les utilisateurs authentifiés, déplacer le stockage du cache sur un volume dimensionné,
appliquer des quotas disques, et alerter sur l’usage des inodes. L’optimisation n’était pas mauvaise ; c’était l’absence de garde‑fous.
Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la situation
Un site de contenu faisait tourner WordPress avec un pipeline de déploiement strict : releases immuables, configs en contrôle de version, et un preflight exécutant nginx -t,
un contrôle de syntaxe PHP sur le code personnalisé, et un smoke test qui demandait /, /wp-login.php, et un asset statique.
Un ingénieur a mergé un changement de règles de réécriture Nginx pour gérer une structure d’URL legacy. La config est passée en syntaxe, mais le smoke test a échoué : la page d’accueil renvoyait 500.
Le pipeline a stoppé le déploiement automatiquement et a gardé l’ancienne config active. Pas de page d’incident. Pas de réunion d’urgence. Juste un job échoué et un ingénieur légèrement agaçant.
L’erreur était subtile : une règle de réécriture référençait un groupe de capture nommé qui n’existait pas sur certains chemins, déclenchant une boucle de redirection interne et un 500.
Parce que le smoke test incluait la page d’accueil et quelques URLs représentatives, il l’a attrapé immédiatement.
La morale est vigoureusement peu sexy : les vérifications pré-déploiement et les smoke tests coûtent moins cher que les actions héroïques. Vous n’avez pas besoin de tests parfaits ; il vous faut quelques contrôles qui échouent bruyamment.
Erreurs courantes : symptôme → cause racine → correctif
La manière la plus rapide de déboguer est de reconnaître des motifs. La manière la plus lente est de traiter chaque 500 comme s’il était totalement nouveau.
Voici les erreurs que je vois régulièrement en production.
1) « 500 seulement sur /wp-admin » → épuisement mémoire ou hooks de plugin admin → augmenter la mémoire proprement et corriger le plugin
- Symptôme : La page d’accueil charge ; wp-admin renvoie 500.
- Cause racine : Les pages admin chargent plus de code (plugins, éditeurs, builders). Limite mémoire trop basse ou un plugin provoque une fatale dans des hooks réservés à l’admin.
- Fix : Cherchez dans les logs PHP « Allowed memory size exhausted », fixez la mémoire dans
php.ini(PHP-FPM), pas seulement dans wp-config, et mettez à jour/désactivez le plugin.
2) « 500 après activation des permalinks » → mauvaise config de réécriture → restaurer les règles de base
- Symptôme : Ça marche avec
?p=123, échoue sur les URLs propres. - Cause racine :
mod_rewritemanquant (Apache), mauvaistry_files(Nginx), ou.htaccesscorrompu. - Fix : Validez la configuration de réécriture du serveur, régénérez les permaliens, gardez les règles de réécriture minimales.
3) « 500 après mise à jour PHP » → incompatibilité d’extensions ou code déprécié → aligner extensions et mettre à jour le code
- Symptôme : Le site meurt juste après le changement de version PHP.
- Cause racine : Un plugin/thème utilise des fonctions supprimées/dépréciées ; des extensions requises ne sont pas installées pour la nouvelle version PHP.
- Fix : Consultez les logs fatals, installez les modules manquants, rollbackez PHP si nécessaire, puis mettez à jour plugins/themes pour compatibilité.
4) « 500 intermittents sous charge » → saturation du pool PHP-FPM ou DB lente → scalez ou optimisez, n’augmentez pas seulement les timeouts
- Symptôme : 500 aléatoires pendant les pics de trafic.
- Cause racine : Workers FPM saturés, ou une requête DB lente bloquant des workers. Les timeouts en cascade suivent.
- Fix : Mesurez la RAM par worker, ajustez
pm.max_childrende manière responsable, ajoutez du caching/caché d’objets, optimisez les requêtes lentes, scalez.
5) « 500 après un « petit changement de config » » → reload Nginx/Apache réussi mais comportement cassé → diff des configs et rollback rapide
- Symptôme : Pas de déploiement, mais quelqu’un a modifié la config.
- Cause racine : Mauvais socket upstream, mauvais chemin root, blocs location mal ordonnés, boucles de redirection internes.
- Fix : Rollback de la modification de config en premier, puis réappliquez avec des tests. En incident, la réversibilité bat l’ingéniosité.
6) « 500 plus ‘permission denied’ dans les logs » → dérive de propriété → corrigez owner/groupe et umask
- Symptôme : Les erreurs mentionnent « Permission denied » en lisant des fichiers PHP ou en écrivant cache/upload.
- Cause racine : Fichiers copiés en root ; processus de déploiement incohérent ; durcissement ayant modifié les modes des dossiers.
- Fix : Restaurez la propriété correcte, imposez un utilisateur de déploiement cohérent, et arrêtez d’éditer la production en root sauf si vous aimez les incidents récurrents.
Listes de contrôle / plan étape par étape
Checklist de restauration rapide (objectif : 15–30 minutes)
- Confirmer la source du 500 : curl des en-têtes ; contournez le CDN si possible.
- Vérifier le log d’erreurs du serveur web : chercher FastCGI/fatales PHP, erreurs de permission, boucles de réécriture.
- Vérifier les logs PHP-FPM : fatales, max_children atteint, segfaults, triggers slowlog.
- Vérifier la sanity de la config :
nginx -t/apachectl configtest. - Vérifier disque + inodes : des disques pleins provoquent des échecs « mystères ».
- Quarantaine des plugins : renommez
wp-content/pluginssi les logs indiquent des erreurs côté plugin. - Thème de secours : renommez le répertoire du thème actif si le thème est impliqué.
- Restaurer un connu bon : revert du dernier déploiement, restauration depuis backup/snapshot si corruption suspectée.
- Supprimer les changements de debug temporaires : désactivez WP_DEBUG et retirez les endpoints de test.
Checklist d’analyse racine et durcissement (objectif : même jour)
- Rendre les logs interrogeables : centralisez Nginx/Apache + PHP-FPM avec des request IDs.
- Ajouter des smoke tests : page d’accueil, wp-login, un post représentatif, et un asset statique.
- Verrouiller le déploiement : propriété cohérente, pas d’éditions root ad hoc, répertoires de release immuables si possible.
- Surveiller les bons indicateurs : % disque, % inode, queue/enfants PHP-FPM, taux 5xx, latence DB.
- Définir le rollback : une commande ou un bouton. Si le rollback nécessite une réunion, ce n’est pas un rollback.
- Auditer les plugins : supprimer les plugins abandonnés, fixer les versions, tester les mises à jour en staging.
Blague #2 : La seule chose plus permanente qu’un correctif temporaire est le ticket marqué « ça n’arrivera plus ».
Faits intéressants et contexte historique (qui aident vraiment au débogage)
- HTTP 500 existe depuis les débuts de HTTP/1.0, mais il a toujours été prévu comme un fourre-tout—ce qui signifie que vous devez vous fier aux logs, pas au code d’état.
- WordPress est né d’un fork de b2/cafelog ; son écosystème de plugins a explosé tôt, et cette extensibilité est une source fréquente de surprises à l’exécution.
- .htaccess existe principalement à cause de l’hébergement mutualisé : les overrides par répertoire permettent aux utilisateurs de modifier les réécritures sans root. Cela leur permet aussi de casser les choses sans root.
- « White Screen of Death » est souvent une fatale PHP avec l’affichage d’erreurs désactivé. L’utilisateur voit du vide ; les logs voient la vérité.
- PHP-FPM est devenu le modèle de déploiement courant parce qu’il gère mieux les processus que le CGI classique et est plus flexible que mod_php pour les stacks modernes.
- OPcache réduit dramatiquement le CPU en mettant en cache le bytecode compilé, mais des caches obsolètes peuvent imiter des 500 « aléatoires » après déploiement.
- L’épuisement d’inodes est plus ancien que le cloud : les systèmes de fichiers ext peuvent manquer d’inodes avant les octets, et les apps web avec beaucoup de petits fichiers de cache sont des candidats naturels.
- Beaucoup de CDNs renvoyaient historiquement des pages 5xx génériques même quand l’origine renvoyait un code spécifique, ce qui a appris aux équipes à diagnostiquer la mauvaise couche en premier.
- Le modèle de réécriture de WordPress dépend du front controller (index.php gère les « pretty URLs »), ce qui explique pourquoi une mauvaise réécriture se traduit par une panne totale du site.
FAQ
1) Pourquoi WordPress affiche-t-il un 500 au lieu d’un message d’erreur utile ?
En production, l’affichage des erreurs PHP est généralement désactivé (à raison), donc les fatales n’affichent pas une jolie trace. Le serveur web renvoie 500 parce que l’upstream a échoué.
Votre message d’aide se trouve dans les logs.
2) Une erreur 500 est-elle toujours causée par des plugins ?
Non. Les plugins sont fréquents, mais les mauvaises configurations, extensions PHP manquantes, permissions, disque plein et saturation du pool PHP-FPM sont tout aussi courants dans des environnements réels.
Commencez par les logs, pas par la superstition.
3) Quelle est la manière la plus rapide et sûre de désactiver tous les plugins ?
Renommez wp-content/plugins en autre chose. WordPress ne chargera pas les plugins normaux. Si le site revient, vous avez confirmé la classe du problème.
Rappelez-vous que les mu-plugins continuent de se charger.
4) Si j’augmente memory_limit, cela corrigera-t-il les 500 ?
Parfois. Si le log indique « memory exhausted », oui—augmenter peut restaurer le service. Mais cela peut aussi masquer une fuite mémoire ou un plugin trop gourmand.
Assurez-vous aussi de changer la limite au bon endroit (PHP-FPM pool/php.ini), pas seulement via les constantes WordPress.
5) Pourquoi j’obtiens un 500 seulement parfois ?
Les 500 intermittents viennent généralement d’un comportement dépendant de la charge : saturation PHP-FPM, base de données lente, conditions de course dans les couches de cache, disque qui se remplit progressivement,
ou une dépendance upstream instable. Cherchez des corrélations avec le trafic et les métriques de ressources.
6) Et si les logs sont vides ?
Alors vous regardez au mauvais endroit ou la journalisation est mal configurée. Confirmez quel serveur web est actif, confirmez les chemins de logs, et vérifiez journald.
Vérifiez aussi que la requête atteint bien l’origine (contournez CDN/WAF et confirmez).
7) Je suis sur Apache. Dois-je supprimer .htaccess ?
Ne supprimez pas ; mettez-le en quarantaine. Renommez-le pour pouvoir le restaurer rapidement. Si le retirer corrige le problème, reconstruisez un .htaccess WordPress minimal et réappliquez les changements prudemment.
8) Un problème de base de données peut-il apparaître comme un 500 ?
Oui. Bien que WordPress affiche souvent un message de connexion DB, certaines couches de cache d’objets et du code personnalisé lancent des exceptions qui deviennent des 500.
Consultez les logs PHP pour des exceptions DB et les logs web pour des timeouts upstream.
9) Comment savoir si c’est PHP-FPM ou le code WordPress ?
Créez un fichier PHP minimal temporaire (ou utilisez un health check existant) et sollicitez‑le via le même vhost.
Si ça fonctionne, PHP-FPM est probablement OK et c’est le chemin code WordPress qui échoue. Supprimez l’endpoint ensuite.
10) Quelle est la prévention la plus efficace contre les incidents 500 récurrents ?
Un pipeline de déploiement avec smoke tests et un rollback en une étape. Vous pouvez survivre à des plugins cassés si vous pouvez revenir en arrière en quelques secondes au lieu de débattre dans le chat.
Conclusion : prochaines étapes qui réduisent vraiment les répétitions
Les erreurs 500 WordPress ne sont pas rares, et elles ne sont pas mystiques. Elles disent simplement que « quelque chose a échoué » tout en refusant de dire quoi.
Votre travail est de le faire parler : confirmez la couche, lisez les logs, isolez le runtime, puis avancez avec un correctif—or revenez en arrière en toute confiance.
Si vous voulez une séquence pratique à implémenter après l’incendie, faites ceci :
- Assurez-vous que les logs Nginx/Apache et PHP-FPM sont conservés, pivotés et interrogeables.
- Ajoutez un petit ensemble de smoke tests qui s’exécutent à chaque déploiement et chaque changement de config.
- Mettez des garde‑fous sur le stockage : alertes pour disque et inodes, emplacements de cache sensés et limites.
- Standardisez la propriété des fichiers et les mécanismes de déploiement pour que la dérive des permissions cesse d’être un personnage récurrent de vos rapports d’incident.
- Testez les mises à jour de plugin/thème en staging, et traitez les montées de version PHP comme des projets de compatibilité, pas comme une « maintenance mineure ».
Faites cela, et la prochaine fois que vous verrez « 500 Internal Server Error », ce sera une réparation de 15 minutes avec un postmortem propre—plutôt qu’une soirée de débogage interprétatif.