Le WordPress d'aujourd'hui, décodé pour les développeurs

Extensions

« There has been a critical error » sur une extension avec l’Interactivity API

Deux blocs déclarent le même store côté client avec l'Interactivity API de WordPress 6.5 : diagnostic d'un conflit qui plante la page sans message clair.

Par Clément Hadrot • 10 septembre 2024 • 4 min de lecture • Aucun commentaire
« There has been a critical error » sur une extension avec l'Interactivity API

« There has been a critical error on this website. » Ce message générique de WordPress, affiché à la place de la page publique, est en soi une non-information pour qui doit diagnostiquer une panne. Sur un projet utilisant plusieurs blocs interactifs construits avec l’Interactivity API, stable depuis WordPress 6.5, ce message est apparu après l’ajout d’une troisième extension de blocs interactifs, sans qu’aucun changement de code n’ait été fait sur les deux premières.

Le réflexe habituel — activer WP_DEBUG et relire le journal — donnait ici une fausse piste : aucune erreur PHP fatale n’apparaissait dans les journaux. Le plantage ne venait pas du serveur, mais du navigateur, et la page blanche affichée côté public masquait en réalité une erreur JavaScript qui empêchait l’hydratation des blocs interactifs.

Symptôme : une page qui s’affiche mais ne réagit plus

En creusant via la console du navigateur plutôt que les journaux serveur, l’erreur réelle apparaissait clairement : Uncaught Error: Store "monagence/panier" is already defined. Deux blocs distincts, développés par deux équipes différentes à des moments différents, avaient chacun déclaré un store avec le même espace de noms via store(), l’API JavaScript centrale de l’Interactivity API :

// Bloc A
import { store } from '@wordpress/interactivity';
store( 'monagence/panier', {
    state: { count: 0 },
} );

// Bloc B, ajouté plus tard, même namespace
import { store } from '@wordpress/interactivity';
store( 'monagence/panier', {
    state: { total: 0 },
} );

Pourquoi WordPress ne prévient pas plus clairement

L'essentiel à retenir : Le conflit se joue côté client, pas côté PHP ; Deux stores identiques s'écrasent silencieusement ; Namespacer chaque store dès sa création évite le problème

L’Interactivity API refuse d’écraser silencieusement un store déjà déclaré, et lève une exception JavaScript au chargement de la page. Cette exception, non interceptée, interrompt l’exécution du script d’hydratation pour l’ensemble de la page, pas seulement pour le bloc fautif. Résultat visible côté public : les interactions des autres blocs, parfaitement codés par ailleurs, cessent également de fonctionner, ce qui brouille encore le diagnostic en donnant l’impression d’une panne généralisée plutôt que d’un conflit ponctuel.

Le message « critical error » de WordPress, lui, ne s’affiche que dans certains contextes serveur particuliers (par exemple lorsqu’un fatal error handler PHP est déclenché indirectement par un rendu de bloc qui dépend du script planté) ; dans le cas le plus fréquent, c’est simplement la page qui reste figée sans aucun message, ce qui est presque pire pour un client qui signale « le site ne marche plus » sans plus de détail.

Le correctif : namespacer réellement chaque store

La convention recommandée par la documentation de l’Interactivity API est de préfixer chaque namespace par le nom de l’extension ou du thème, pas seulement par celui de l’agence, pour garantir l’unicité même entre extensions de fournisseurs différents :

  • Utiliser un namespace complet et spécifique au bloc, par exemple monagence/panier-boutique-a plutôt qu’un générique monagence/panier.
  • Ne jamais partager un même namespace entre deux blocs qui gèrent un état différent, même s’ils semblent proches fonctionnellement.
  • Si un état doit réellement être partagé entre plusieurs blocs, le faire via un seul store déclaré une seule fois, importé par les deux blocs plutôt que redéclaré.

Prévenir la récidive en environnement multi-équipes

Sur un projet où plusieurs extensions interactives coexistent, développées par des prestataires différents, la vraie prévention consiste à documenter les namespaces utilisés dans un registre partagé — un simple fichier NAMESPACES.md dans le dépôt du thème suffit — pour qu’un nouveau développeur vérifie l’absence de collision avant de créer un store. Un test end-to-end minimal, qui charge la page et vérifie l’absence d’erreur JavaScript dans la console, permet aussi de détecter ce type de conflit avant la mise en production plutôt qu’après.

Depuis cet incident, la checklist de recette inclut systématiquement un contrôle de la console navigateur sur les pages contenant des blocs interactifs, pas seulement une vérification visuelle de l’affichage.

Prévention

Ce type de conflit est spécifique à l’Interactivity API et ne concerne pas les block bindings, qui reposent sur un mécanisme entièrement différent côté PHP. La leçon à retenir : une erreur JavaScript non interceptée peut se manifester côté WordPress comme une panne generale de la page, bien au-delà du bloc réellement fautif, ce qui rend le réflexe « ouvrir la console avant les journaux serveur » indispensable dès qu’un site utilisant l’Interactivity API cesse de réagir sans message d’erreur clair.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi