Si vous avez déjà vu l’éditeur de blocs rester bloqué sur “Chargement…” ou afficher “L’éditeur a rencontré une erreur inattendue”, vous avez probablement un problème côté API REST, scripts admin, ou cache/sécurité. Sur WordPress 6.9.4 (avril 2026), Gutenberg dépend encore plus qu’avant d’un admin sain : REST, nonces, scripts versionnés et réponses JSON propres.
Le problème
Les messages typiques que je retrouve dans la console navigateur (ou dans l’UI) ressemblent à ceux-ci :
"The editor has encountered an unexpected error."
"Updating failed. The response is not a valid JSON response."
"Error: The REST API encountered an error."
"GET https://example.com/wp-json/wp/v2/types/post?context=edit 403 (Forbidden)"
Ça apparaît dans l’admin, sur Articles → Ajouter / Pages → Modifier, parfois uniquement sur certains types de contenus (CPT), et souvent juste après :
- une mise à jour de plugin de sécurité/cache,
- un changement de règle WAF/CDN (Cloudflare, Sucuri, ModSecurity),
- l’ajout d’un snippet qui “nettoie” le HTML,
- une migration (URL, HTTPS, reverse proxy),
- ou une mise à jour de thème (Avada) / page builder (Elementor, Divi 5) qui ajoute des scripts admin.
Ce guide s’adresse à des utilisateurs intermédiaires : vous savez ouvrir la console, lire un log, poser un MU-plugin, et utiliser WP-CLI. À la fin, vous saurez isoler la cause (REST, JS, cache, sécurité, PHP) et appliquer un correctif propre, compatible WordPress 6.9.4+ et PHP 8.1+.
Résumé rapide
- Commencez par la console : l’erreur visible (403 REST, JSON invalide, fichier JS 404) dicte la suite.
- Test REST immédiat :
/wp-json/wp/v2/types/post?context=editen étant connecté, puis comparez avec un compte admin. - Désactivez les interférences : plugins de sécurité/cache, snippets, optimisation JS/CSS, CDN, puis réactivez un par un.
- Activez des logs propres :
WP_DEBUG_LOG+ Query Monitor, et cherchez “REST”, “nonce”, “headers already sent”, “fatal”. - Ne “corrigez” pas Gutenberg avec jQuery : la plupart des pannes viennent d’un enqueue ou d’un filtre qui modifie les réponses JSON.
- Si vous êtes sur un builder : Divi 5/Elementor/Avada ajoutent des assets admin ; un conflit d’optimisation ou de sécurité est fréquent.
Les symptômes
Voici les symptômes que je vois le plus souvent (du plus commun au plus “piégeux”).
- Écran blanc dans l’éditeur avec un spinner infini.
- Message UI : “L’éditeur a rencontré une erreur inattendue”.
- Erreur de publication : “La mise à jour a échoué. La réponse n’est pas une réponse JSON valide.”
- Console navigateur (F12 → Console / Réseau) :
- 403/401 sur
/wp-json/...(souvent WAF ou règle de sécurité), - 500 sur une route REST (fatal PHP côté serveur),
- 404 sur un fichier
wp-includes/js/dist/*.min.js(cache/CDN ou déploiement incomplet), - erreurs CORS ou CSP (headers de sécurité trop stricts),
Unexpected token < in JSON(HTML injecté dans une réponse JSON, typiquement un warning PHP ou une page 403 HTML).
- 403/401 sur
- Ça marche en local mais pas en production : CDN, cache agressif, WAF, ou différence de PHP/extensions.
- Ça marche pour un admin mais pas pour un éditeur : capacités, nonces, ou plugin qui filtre selon le rôle.
- Ça casse uniquement sur un CPT :
show_in_restmanquant, ou route REST custom qui fatal.
Tableau de diagnostic rapide
| Symptôme | Cause probable | Vérification | Solution |
|---|---|---|---|
| “Réponse JSON invalide” | HTML/warning injecté dans REST | Ouvrir la réponse réseau de /wp-json/... |
Désactiver plugin/snippet, corriger warnings, voir Solution 1 |
403 sur /wp-json/ |
WAF, règle sécurité, Basic Auth | Tester REST en navigation privée + logs WAF | Whitelist REST + headers, voir Solution 1 |
| Spinner infini, erreurs JS | Enqueue admin cassé / optimisation JS | Console: “Cannot read properties of undefined” | Corriger enqueue, exclure assets, voir Solution 2 |
404 sur wp-includes/js/dist/ |
Déploiement incomplet / cache CDN | Tester en désactivant CDN, purge cache | Purge + re-déploiement, voir Solution 3 |
| 500 sur une route REST | Fatal PHP (plugin/thème) | WP_DEBUG_LOG + Query Monitor | Corriger fatal, rollback, voir Solution 1 |
Pourquoi ça arrive
Version simple : l’éditeur de blocs est une application JavaScript qui parle en permanence à votre site via l’API REST. Si REST renvoie autre chose que du JSON propre (ou si les scripts nécessaires ne se chargent pas), l’éditeur ne peut pas initialiser son état.
Voici ce qui se passe en coulisses (version technique) :
- Gutenberg charge des bundles depuis
wp-includes/js/dist/et des styles admin. - Il récupère les données via des endpoints REST (types, taxonomies, settings, autosaves, post, etc.).
- Il envoie des requêtes authentifiées avec des nonces. Si un plugin modifie les en-têtes, bloque des routes, ou met en cache des réponses “edit context”, ça casse.
- Un warning PHP, un “notice”, ou même un espace avant
<?phppeut suffire à polluer une réponse JSON.
Causes probables (du plus fréquent au plus rare) :
- Blocage REST par sécurité/cache/CDN (403, challenge, Basic Auth, règle ModSecurity).
- Réponse REST polluée par un warning PHP, un
var_dump(), ou un plugin qui imprime du HTML. - Optimisation JS/CSS qui combine/minifie l’admin (ou “defer” des scripts WordPress).
- Enqueue admin mal fait (dépendances manquantes, hook inadapté, chargement global sur toutes les pages).
- CSP/headers de sécurité trop stricts (bloque
blob:,data:, ou les scripts/styles attendus). - Incohérence de cache (service worker, cache navigateur, object cache, CDN) qui sert des assets d’une autre version.
- Problème serveur (permissions fichiers, déploiement incomplet, opcache, extension PHP manquante).
Prérequis avant de commencer
- Sauvegarde fichiers + base (ou snapshot si vous êtes sur un hébergeur managé). Ne testez pas “au hasard” en prod.
- Environnement de test : staging idéalement, ou au minimum une fenêtre de maintenance.
- Versions : WordPress 6.9.4 et PHP 8.1+ recommandés. Vérifiez dans Outils → Santé du site.
- Plugins utiles :
- Query Monitor (requêtes, erreurs PHP, hooks, REST).
- Health Check & Troubleshooting (mode dépannage sans impacter les visiteurs).
- Logs : activez temporairement
WP_DEBUG_LOG(sans afficher en front).
Configuration recommandée (temporaire) dans wp-config.php :
<?php
// Active le debug sans afficher les erreurs à l'écran (évite de polluer des réponses JSON).
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_DISPLAY', false );
// Log dans wp-content/debug.log
define( 'WP_DEBUG_LOG', true );
// Optionnel : réduit les "notices" bruyantes de certains plugins (à ajuster selon votre besoin).
// error_reporting( E_ALL & ~E_NOTICE & ~E_DEPRECATED );
Risque sécurité : ne laissez pas WP_DEBUG activé en permanence sur un site public. Les logs peuvent contenir des chemins, requêtes, voire des infos sensibles.
Solution 1 : l’API REST est bloquée (403/401/500) et Gutenberg ne peut plus démarrer
Quand Gutenberg ne charge pas, je commence toujours par une requête REST simple. Parce que si REST est cassée, vous pouvez corriger tous les scripts du monde : l’éditeur restera instable.
Diagnostic
- Ouvrez l’éditeur en admin, puis F12 → onglet Réseau.
- Filtrez sur
wp-json. - Repérez la première requête en erreur (souvent
types,settings,posts). - Cliquez la requête → regardez la réponse :
- Si vous voyez du HTML (page d’erreur, challenge, login), vous avez trouvé.
- Si vous voyez un JSON d’erreur WordPress, notez
codeetmessage.
Test rapide en ligne de commande (si vous avez WP-CLI + cookie/nonce c’est plus complexe). Pour un test simple, faites-le au navigateur en étant connecté :
URL : https://votre-site.tld/wp-json/wp/v2/types/post?context=edit
Si vous obtenez 403/401, ou une page HTML, la cause est presque toujours externe à WordPress (WAF, plugin sécurité, Basic Auth, reverse proxy).
Cas fréquent : un plugin bloque REST via un filtre trop agressif
J’ai souvent croisé des snippets qui “désactivent l’API REST” pour des raisons de sécurité, mais ils cassent l’éditeur (et parfois Elementor/Divi/Avada côté admin aussi).
AVANT (cassé)
<?php
// Mauvaise idée : bloque l'API REST pour tout le monde, y compris l'admin.
// Résultat : Gutenberg ne peut plus charger.
add_filter( 'rest_authentication_errors', function( $result ) {
return new WP_Error(
'rest_disabled',
'REST API désactivée',
array( 'status' => 403 )
);
} );
APRÈS (corrigé, restriction ciblée)
<?php
/**
* Restriction REST plus sûre : ne bloque pas l'admin, et limite seulement certaines routes publiques.
* À placer dans un plugin (ou MU-plugin), pas dans functions.php si vous changez souvent de thème.
*/
add_filter( 'rest_authentication_errors', function( $result ) {
// Si une authentification a déjà échoué/réussi, respectez le résultat.
if ( ! empty( $result ) ) {
return $result;
}
// Autorisez toujours les utilisateurs connectés (Gutenberg en dépend).
if ( is_user_logged_in() ) {
return $result;
}
// Exemple : bloquer uniquement une route custom publique (à adapter).
$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? (string) $_SERVER['REQUEST_URI'] : '';
if ( str_contains( $request_uri, '/wp-json/mon-namespace/v1/' ) ) {
return new WP_Error(
'rest_forbidden',
'Accès REST interdit.',
array( 'status' => 403 )
);
}
return $result;
} );
Pourquoi ça corrige : Gutenberg appelle des endpoints REST en contexte edit qui nécessitent une session connectée. Bloquer REST “globalement” revient à débrancher l’API interne de l’éditeur.
Point de vigilance : ce type de filtre doit être précis. Bloquer par “présence de /wp-json/” est un anti-pattern. Si vous voulez réellement réduire l’exposition REST, faites-le route par route, et testez l’admin.
Cas fréquent : “Réponse JSON invalide” à cause d’un warning PHP
Quand la réponse REST commence par du HTML, Gutenberg affiche souvent “réponse JSON invalide”. La cause réelle est parfois un simple warning PHP imprimé avant le JSON.
AVANT (cassé)
<?php
// Exemple réaliste : un plugin/thème affiche un warning (variable non définie) et pollue la réponse REST.
add_action( 'init', function() {
// Mauvais : echo en init, peut s'exécuter pendant une requête REST.
if ( isset( $_GET['debug'] ) ) {
echo "DEBUG"; // Pollue la sortie JSON.
}
} );
APRÈS (corrigé)
<?php
// Ne jamais "echo" dans le cycle WordPress global.
// Utilisez error_log() et limitez à WP_DEBUG.
add_action( 'init', function() {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG && isset( $_GET['debug'] ) ) {
error_log( 'Debug init déclenché' );
}
} );
Pourquoi ça corrige : l’API REST doit renvoyer un JSON strict. Le moindre caractère en sortie (warning, BOM, echo) casse le parse JSON côté navigateur.
Cas fréquent : blocage WAF/CDN (403, challenge, Basic Auth)
Si la réponse 403 est une page HTML “Access denied” ou un challenge, WordPress n’y est pour rien.
- Désactivez temporairement le WAF/CDN (ou passez en “dev mode”).
- Autorisez explicitement
/wp-json/et/wp-admin/admin-ajax.php. - Si vous avez un Basic Auth sur staging, Gutenberg peut échouer selon la config du navigateur. Dans ce cas, autorisez l’admin IP, ou désactivez Basic Auth le temps d’éditer.
Pour comprendre le contrat REST côté WordPress, la doc officielle est ici : REST API Handbook.
Solution 2 : scripts de l’éditeur cassés (enqueue, dépendances, ordre de chargement)
Le deuxième grand classique : un thème ou plugin charge un script dans l’admin, mais :
- sur le mauvais hook,
- sans dépendances,
- ou en surchargeant une lib (React, lodash) que WordPress fournit déjà.
Résultat : erreurs JS du type wp is not defined, Cannot read properties of undefined, ou un crash silencieux.
Diagnostic
- F12 → Console : notez la première erreur (pas la 15e). La première est souvent la cause.
- F12 → Réseau : cherchez un fichier JS en 404/blocked.
- Désactivez temporairement les plugins d’optimisation (minify/combine/defer) qui touchent l’admin.
Cas fréquent : enqueue global sur admin_enqueue_scripts sans cibler l’écran
J’ai souvent vu un script “admin” chargé partout, et il suppose l’existence de wp.data (Gutenberg) même sur des écrans qui ne le chargent pas. Ou inversement : il écrase des variables globales.
AVANT (cassé)
<?php
// Mauvais : charge un script partout dans l'admin, sans dépendances, et trop tôt.
// Sur l'écran de l'éditeur, ça peut entrer en conflit.
add_action( 'admin_enqueue_scripts', function() {
wp_enqueue_script(
'mon-admin',
get_stylesheet_directory_uri() . '/assets/admin.js',
array(), // Oublie des dépendances éventuelles.
'1.0',
true
);
} );
APRÈS (corrigé : ciblage + dépendances + versioning)
<?php
/**
* Charge un script admin uniquement sur l'éditeur de blocs, avec des dépendances correctes.
* Compatible WP 6.9.4+.
*/
add_action( 'admin_enqueue_scripts', function( $hook_suffix ) {
// Cible les écrans post.php (édition) et post-new.php (création).
if ( ! in_array( $hook_suffix, array( 'post.php', 'post-new.php' ), true ) ) {
return;
}
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
if ( ! $screen ) {
return;
}
// Optionnel : ne chargez que pour certains post types.
$allowed_post_types = array( 'post', 'page' );
if ( empty( $screen->post_type ) || ! in_array( $screen->post_type, $allowed_post_types, true ) ) {
return;
}
$src = get_stylesheet_directory_uri() . '/assets/admin-editor.js';
$path = get_stylesheet_directory() . '/assets/admin-editor.js';
wp_enqueue_script(
'mon-admin-editor',
$src,
array( 'wp-data', 'wp-edit-post', 'wp-element' ), // Dépendances Gutenberg.
file_exists( $path ) ? filemtime( $path ) : '1.0.0',
true
);
} );
Pourquoi ça corrige : vous évitez de polluer tout l’admin, vous chargez uniquement là où Gutenberg est présent, et vous déclarez des dépendances stables. Le versioning par filemtime() évite aussi les caches “fantômes” après déploiement.
Cas fréquent : un plugin charge React/ReactDOM à la main
Si un plugin embarque sa propre version de React (ou la charge via CDN) dans l’admin, vous pouvez obtenir des erreurs difficiles à diagnostiquer, surtout après une mise à jour WordPress. WordPress fournit déjà les packages nécessaires pour l’éditeur.
AVANT (cassé)
<?php
// Anti-pattern : charger React via CDN dans l'admin.
// Peut casser Gutenberg (deux React différents).
add_action( 'admin_enqueue_scripts', function() {
wp_enqueue_script( 'react', 'https://unpkg.com/react@18/umd/react.production.min.js', array(), null, true );
wp_enqueue_script( 'react-dom', 'https://unpkg.com/react-dom@18/umd/react-dom.production.min.js', array( 'react' ), null, true );
} );
APRÈS (corrigé : utiliser les packages WordPress)
<?php
// Utilisez les packages WordPress (wp-element) au lieu de React embarqué.
add_action( 'admin_enqueue_scripts', function( $hook_suffix ) {
if ( ! in_array( $hook_suffix, array( 'post.php', 'post-new.php' ), true ) ) {
return;
}
wp_enqueue_script(
'mon-ui',
plugin_dir_url( __FILE__ ) . 'assets/mon-ui.js',
array( 'wp-element', 'wp-components', 'wp-i18n' ),
'1.0.0',
true
);
} );
Documentation utile : Package wp-element et Block Editor Handbook.
Compatibilité Divi 5 / Elementor / Avada
- Divi 5 : si vous activez des options de performance qui “optimisent” l’admin, testez Gutenberg après. Divi charge parfois des assets editor pour ses modules ; excluez
/wp-admin/des optimisations agressives. - Elementor : même si Elementor a son propre éditeur, il s’intègre à l’admin WP. Un plugin d’optimisation qui combine les scripts admin peut casser Gutenberg et l’écran Elementor.
- Avada : Fusion Builder et Avada Live chargent des scripts lourds. Si vous avez un cache/minify qui touche l’admin, Avada est souvent le premier à “révéler” le problème.
Solution 3 : cache, sécurité et CSP (Content-Security-Policy) qui cassent l’admin
Quand je vois Gutenberg qui marche “une fois sur deux”, ou uniquement après un hard refresh, je pense cache. Quand je vois des erreurs “Refused to load… because it violates CSP”, je pense headers de sécurité mal calibrés.
Cas fréquent : optimisation qui minifie/concatène l’admin
Beaucoup de plugins d’optimisation ont une option “Optimiser aussi l’administration”. Sur WordPress 6.9.4, c’est souvent une mauvaise idée : l’admin change vite, les bundles sont déjà optimisés, et le risque de casser les dépendances est réel.
Action concrète :
- Désactivez l’optimisation JS/CSS sur
/wp-admin/. - Excluez au minimum :
/wp-includes/js/dist//wp-admin/js/load-scripts.phpetload-styles.php(si utilisés)
- Purge : cache plugin + cache serveur + CDN + navigateur.
Cas fréquent : CSP trop stricte
Une CSP “très sécurisée” peut bloquer des mécanismes utilisés par l’éditeur (selon plugins, médias, iframes, etc.). Les erreurs apparaissent dans la console, pas dans WordPress.
Exemple d’erreur console :
Refused to load the script 'blob:https://example.com/...' because it violates the following Content Security Policy directive...
Si vous gérez CSP via PHP (plugin sécurité, custom headers), testez en assouplissant uniquement pour l’admin. Voici un exemple minimal (à adapter, et à valider avec votre politique sécurité) :
<?php
/**
* Exemple : définir des headers CSP uniquement dans l'admin.
* Attention : une CSP doit être pensée globalement. Ne copiez pas ceci sans comprendre votre surface d'attaque.
*/
add_action( 'send_headers', function() {
if ( ! is_admin() ) {
return;
}
// Exemple volontairement simple. Ajustez selon vos besoins.
// Objectif : éviter de casser des scripts/styles nécessaires à l'éditeur.
header( "Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob:; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self' https:; frame-src 'self';" );
}, 20 );
Pourquoi ça corrige : Gutenberg et certains composants admin peuvent utiliser des URLs blob: / data: (selon fonctionnalités et extensions). Une CSP trop restrictive bloque le chargement/évaluation, et l’app JS ne démarre pas.
Risque sécurité : 'unsafe-inline' et 'unsafe-eval' augmentent le risque XSS. Dans l’idéal, vous n’en voulez pas. Mais dans la vraie vie, beaucoup de stacks WP (plugins inclus) ne sont pas prêtes pour une CSP “strict-dynamic” parfaite. Faites une CSP progressive, et utilisez le mode Report-Only pour itérer.
Cas fréquent : assets d’une ancienne version servis par CDN/opcache
Après une mise à jour WordPress, j’ai déjà vu des wp-includes/js/dist/* servir des fichiers d’une version précédente via CDN. Gutenberg charge alors un mix de versions incompatibles.
Checklist :
- Purger le CDN (et pas seulement le cache plugin).
- Vider l’opcache PHP si vous avez la main (ou redémarrer PHP-FPM).
- Vérifier que le déploiement a bien uploadé tous les fichiers WordPress (surtout en SFTP manuel).
Vérifications après correction
- Ouvrez un article existant et créez-en un nouveau : les deux écrans doivent fonctionner.
- Testez avec un compte Admin puis un compte Éditeur (les capacités REST diffèrent).
- Console : zéro erreur rouge au chargement initial. Quelques warnings peuvent exister, mais pas d’erreur bloquante.
- Réseau : les requêtes
/wp-json/doivent être en 200, et la réponse doit être du JSON. - Test rapide de publication : brouillon → publier → mettre à jour.
Si vous utilisez Elementor/Divi/Avada, ouvrez aussi leurs écrans d’édition : un correctif “admin” doit améliorer l’ensemble, pas seulement Gutenberg.
Si ça ne marche toujours pas
Procédure que j’applique quand le problème résiste (dans cet ordre, parce que ça évite de tourner en rond).
1) Mode dépannage sans impacter les visiteurs
- Activez Health Check et utilisez le mode dépannage.
- Désactivez tous les plugins dans ce mode, gardez le thème actif.
- Testez Gutenberg.
Si ça marche, réactivez les plugins un par un jusqu’au coupable (souvent sécurité, cache, optimisation, ou un plugin de champs personnalisés mal codé).
2) Vérifiez les logs PHP et les erreurs REST
- Ouvrez
wp-content/debug.logjuste après un chargement raté. - Cherchez :
Fatal error,headers already sent,Deprecated(certains deprecations peuvent polluer la sortie si affichées),REST.
Pour comprendre les erreurs “invalid JSON”, la doc officielle sur le debug est ici : Debugging in WordPress.
3) Query Monitor : regardez les erreurs et les requêtes AJAX/REST
Query Monitor affiche les erreurs PHP, les hooks, et parfois les appels HTTP. Sur des pannes Gutenberg, je l’utilise surtout pour :
- repérer un warning qui s’exécute sur une requête REST,
- identifier le plugin responsable via la stack trace,
- voir si l’admin charge des scripts inattendus.
4) Vérifiez la santé du site et les limites serveur
- Mémoire PHP : Gutenberg + builders + gros plugins peuvent pousser. Un manque de mémoire peut provoquer des fatals intermittents.
- Limites :
max_input_varstrop bas peut impacter certains écrans (moins fréquent sur Gutenberg pur, plus sur méta-boxes lourdes). - Permissions : si des fichiers WP core ne sont pas lisibles, vous aurez des 404/500 sur les assets.
5) Reset des permaliens (rare, mais rapide)
Quand REST renvoie des 404 alors que le fichier existe, j’ai déjà vu des règles de réécriture incohérentes après migration.
- Réglages → Permaliens → Enregistrer (sans changer).
6) Vérifiez un conflit de snippets
Les plugins de snippets (ou le functions.php) sont une cause majeure, car une simple erreur de syntaxe casse tout.
- Recherchez une erreur “oubli de point-virgule” ou parenthèse.
- Regardez si un snippet s’exécute sur
init/wp_loadedet fait unecho/var_dump.
7) WP-CLI : vérifier l’intégrité et les versions
Sur un site où je soupçonne un déploiement incomplet, WP-CLI est très efficace :
# Vérifie l'intégrité des fichiers du core WordPress
wp core verify-checksums
# Liste plugins et mises à jour en attente
wp plugin list
wp plugin update --all
# Vérifie la version PHP (vue par WP-CLI)
php -v
Documentation WP-CLI : WP-CLI Commands.
Pièges et erreurs courantes
| Symptôme | Cause probable | Solution recommandée |
|---|---|---|
| “Réponse JSON invalide” après ajout d’un snippet | echo/var_dump ou warning PHP pendant REST |
Supprimer la sortie, utiliser error_log(), corriger warnings (Solution 1) |
| Gutenberg ne charge que sur certains navigateurs | Cache navigateur/service worker ou extension | Test navigation privée, désactiver extensions, purge cache (Solution 3) |
| Erreur JS “wp is not defined” | Script chargé trop tôt ou sur mauvais écran | Cibler post.php/post-new.php + dépendances (Solution 2) |
403 sur /wp-json/ uniquement en production |
WAF/CDN, règle ModSecurity, Basic Auth | Whitelist REST/admin-ajax, logs WAF, bypass (Solution 1) |
| Ça marche après désactivation cache, puis recasse | Plugin d’optimisation réactive “minify admin” | Exclure /wp-admin/ et bundles WP (Solution 3) |
| Erreur après mise à jour WP, fichiers JS en 404 | Déploiement incomplet / CDN sert l’ancienne version | Purge CDN + wp core verify-checksums (Solution 3) |
| Le code est “au bon endroit” mais ne marche pas | Copié dans le mauvais fichier (plugin vs thème enfant), ou hook inadapté | Mettre en MU-plugin, vérifier hook et priorité |
| Ça casse seulement pour le rôle Éditeur | Capacités REST/nonce, plugin de rôles | Tester routes REST avec ce rôle, corriger capacités |
Erreurs que je vois souvent chez des utilisateurs intermédiaires :
- Tester directement sur production sans sauvegarde, puis “réparer” en urgence.
- Ajouter un snippet trouvé sur un vieux tutoriel (pré-6.x) qui bloque REST “pour la sécurité”.
- Oublier de purger le cache CDN après une mise à jour WordPress.
- Utiliser un hook trop global (ex.
init) pour imprimer du HTML ou charger du JS. - Minifier/concaténer l’admin “pour gagner 0,2s” et perdre l’éditeur.
Variante / alternative
Méthode sans code : isoler avec Health Check + rollback contrôlé
- Health Check → mode dépannage → désactivez plugins par catégorie (sécurité/caching/optimisation).
- Si le coupable est identifié, mettez à jour ou remplacez-le.
- Si le bug vient d’une mise à jour récente, faites un rollback temporaire (plugin) puis ouvrez un ticket chez l’éditeur.
Méthode plus avancée : MU-plugin “garde-fou” pour journaliser les erreurs REST
Quand un site est complexe (Avada + Elementor + sécurité + cache), je pose parfois un MU-plugin temporaire pour loguer les erreurs REST sans casser la prod.
<?php
/**
* Plugin Name: MU - Debug REST pour éditeur de blocs
* Description: Journalise les erreurs REST (temporaire) pour diagnostiquer Gutenberg.
* Author: Votre équipe
* Version: 1.0.0
*
* À placer dans wp-content/mu-plugins/mu-debug-rest.php
*/
add_filter( 'rest_request_after_callbacks', function( $response, $handler, $request ) {
// Ne loguez que si WP_DEBUG est actif pour éviter du bruit en prod.
if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
return $response;
}
if ( is_wp_error( $response ) ) {
error_log( '[REST][WP_Error] route=' . $request->get_route() . ' code=' . $response->get_error_code() . ' message=' . $response->get_error_message() );
return $response;
}
if ( $response instanceof WP_REST_Response ) {
$status = $response->get_status();
if ( $status >= 400 ) {
error_log( '[REST][HTTP ' . $status . '] route=' . $request->get_route() );
}
}
return $response;
}, 10, 3 );
Ce garde-fou aide à corréler un écran Gutenberg cassé avec une route REST précise.
Éviter ce problème à l’avenir
- Ne bloquez pas REST globalement. Si vous durcissez la sécurité, faites-le par routes, rôles, et contextes. Testez l’admin à chaque changement.
- N’optimisez pas l’admin (minify/combine/defer) sauf cas très maîtrisé. Les gains sont minimes, les risques énormes.
- Chargez vos scripts admin proprement :
- ciblage par écran (
$hook_suffix+get_current_screen()), - dépendances
wp-*déclarées, - versioning fiable (
filemtimeen environnement simple).
- ciblage par écran (
- Surveillez les warnings PHP : en PHP 8.1+, certains patterns déclenchent plus de warnings/deprecations. Un warning affiché peut casser du JSON.
- Process de mise à jour : staging → purge caches → prod. Et après une mise à jour WordPress, purge CDN systématique.
- Headers de sécurité : déployez CSP en Report-Only d’abord, puis durcissez progressivement. Sinon vous allez “casser l’admin” au prochain plugin qui ajoute une iframe ou un blob.
Références utiles côté PHP : PHP error handling configuration.
Ressources
- REST API Handbook (WordPress.org)
- Block Editor Handbook
- Debugging in WordPress
- Health Check & Troubleshooting (plugin)
- Query Monitor (plugin)
- WordPress Core Trac (tickets et historiques)
- Dépôt GitHub Gutenberg (issues)
- WP-CLI commands
Questions fréquentes
Pourquoi Gutenberg affiche “La réponse n’est pas une réponse JSON valide” ?
Parce que la requête REST attend du JSON, mais reçoit autre chose (HTML d’erreur 403/500, warning PHP, sortie parasite). Ouvrez la réponse dans l’onglet Réseau : vous verrez souvent la cause immédiatement.
Est-ce que désactiver l’API REST “pour la sécurité” est une bonne pratique ?
Non, pas globalement. WordPress (et Gutenberg) l’utilise en interne. Si vous durcissez, faites-le par routes et en gardant l’admin fonctionnel. Testez systématiquement /wp-json/wp/v2/types/post?context=edit connecté.
Pourquoi ça marche pour un admin mais pas pour un éditeur ?
Les capacités diffèrent, et certains plugins de rôles/sécurité filtrent REST selon le rôle. Testez avec le compte concerné et vérifiez les 403 sur les routes REST en contexte edit.
Un plugin de cache peut-il casser Gutenberg ?
Oui, surtout s’il met en cache des endpoints REST authentifiés, ou s’il optimise/minifie les scripts de l’admin. Excluez /wp-admin/ et /wp-json/ des règles de cache agressives.
Que faire si j’ai une erreur 500 uniquement sur une route REST ?
C’est presque toujours un fatal PHP déclenché pendant cette requête. Activez WP_DEBUG_LOG, reproduisez, puis regardez debug.log. Query Monitor aide à identifier le plugin/thème responsable.
Divi 5 / Elementor / Avada sont-ils compatibles avec Gutenberg ?
Oui, mais ils ajoutent des scripts et des options de performance. Les conflits viennent surtout des optimisations admin, de la minification, ou de règles de sécurité trop strictes. Si Gutenberg casse, testez aussi l’éditeur du builder : la cause est souvent partagée.
Est-ce que “réenregistrer les permaliens” peut aider ?
Parfois, si REST renvoie des 404 après migration ou changement de serveur. Ce n’est pas le premier réflexe, mais c’est rapide et sans risque.
Est-ce que je peux “réparer Gutenberg” en rechargeant jQuery ou en ajoutant du JS custom ?
C’est généralement un pansement qui masque le vrai problème (REST cassée, scripts en conflit). Corrigez la cause : blocage REST, enqueue mal fait, cache/CDN, ou fatal PHP.
Quels fichiers regarder quand des assets Gutenberg sont en 404 ?
Regardez les URLs wp-includes/js/dist/ et wp-includes/css/dist/. Un 404 peut indiquer un déploiement incomplet ou un CDN qui sert une ancienne version. Un wp core verify-checksums aide beaucoup.
Je vois “Refused to load… violates Content-Security-Policy”. Je fais quoi ?
Assouplissez la CSP pour l’admin, idéalement en Report-Only d’abord. Vérifiez les directives script-src, style-src, connect-src, et l’autorisation de blob:/data: si nécessaire. Faites-le progressivement pour limiter le risque XSS.