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

Blocs Gutenberg

« Block validation failed » sur un bloc après une mise à jour mineure

Diagnostic d'un bloc qui perd son contenu après une mise à jour mineure d'extension, provoqué par un décalage entre save() et les attributs stockés en base.

Par WordPress Développement • 13 septembre 2020 • 4 min de lecture • Aucun commentaire
« Block validation failed » sur un bloc après une mise à jour mineure

« This block contains unexpected or invalid content. » Le message s’affiche dans l’éditeur, sur un bloc qui fonctionnait très bien la veille, juste après la mise à jour d’une extension qui embarque quelques blocs personnalisés. Rien n’a changé dans le contenu de l’article. Et pourtant, l’éditeur refuse de rendre le bloc normalement et propose de le convertir en HTML brut ou de tenter une récupération.

Ce symptôme a une cause presque systématique : la fonction save() du bloc a changé entre l’ancienne et la nouvelle version de l’extension, alors que le contenu déjà enregistré en base a été sérialisé avec l’ancienne version. Gutenberg compare le HTML régénéré par la nouvelle save() à celui stocké dans post_content, et à la moindre différence, il considère le bloc comme invalide.

Comprendre le mécanisme de validation

Quand un article est enregistré, WordPress ne stocke pas uniquement les attributs du bloc : il stocke le résultat de save() tel quel, entouré des commentaires HTML délimiteurs (<!-- wp:namespace/bloc {"attribut":"valeur"} -->). À l’ouverture de l’éditeur, Gutenberg relit les attributs depuis ce commentaire, ré-exécute save() avec la version actuelle du code, et compare le résultat au HTML déjà présent.

Si les deux ne correspondent pas au caractère près — un espace, un attribut manquant, une classe CSS renommée — la validation échoue. Ce comportement est volontaire : il protège contre la perte silencieuse de contenu si le rendu change de façon incompatible.

Reproduire le problème avant de le corriger

La première étape consiste à isoler un article touché et à ouvrir la console du navigateur : Gutenberg y affiche un diff exact entre le HTML attendu et le HTML sauvegardé, généralement sous la forme de deux blocs de texte à comparer ligne à ligne.

Block validation failed
Content generated by `save` function:
<div class="wp-block-wpmoderne-alerte">...</div>
Content of the post:
<div class="wp-block-wpmoderne-alerte alerte--info">...</div>
L'essentiel à retenir : Le message n'indique jamais la vraie cause ; La comparaison porte sur le HTML sérialisé, pas sur les attributs ; Un correctif de save() suffit dans la majorité des cas

Localiser le changement dans save()

Dans cet exemple, une classe conditionnelle alerte--info a été supprimée de la nouvelle version de save(), probablement lors d’une simplification du composant. Le fichier save.js avant et après la mise à jour permet de confirmer :

// Avant la mise à jour
export default function save( { attributes } ) {
    const { type } = attributes;
    return (
        <div className={ `wp-block-wpmoderne-alerte alerte--${ type }` } >
            { attributes.texte }
        </div>
    );
}

// Après la mise à jour (le bug)
export default function save( { attributes } ) {
    return (
        <div className="wp-block-wpmoderne-alerte">
            { attributes.texte }
        </div>
    );
}

Corriger sans perdre le contenu existant

Deux options s’offrent alors, et le choix dépend de l’ampleur du changement voulu. La première, la plus rapide, consiste à revenir à l’ancien comportement de save() pour rester compatible avec le contenu déjà publié. La seconde, plus propre à long terme, consiste à déclarer une deprecated version du bloc qui sait lire l’ancien format et le migrer vers le nouveau :

const v1 = {
    attributes: { type: { type: 'string' }, texte: { type: 'string' } },
    save( { attributes } ) {
        return (
            <div className={ `wp-block-wpmoderne-alerte alerte--${ attributes.type }` }>
                { attributes.texte }
            </div>
        );
    },
};

registerBlockType( 'wpmoderne/alerte', {
    // ... version actuelle
    deprecated: [ v1 ],
} );

Cette seconde approche évite d’avoir à réenregistrer manuellement chaque article concerné : Gutenberg tente automatiquement chaque version dépréciée jusqu’à trouver celle qui valide le contenu existant.

Éviter la récidive

  • Ne jamais modifier save() sans ajouter une entrée deprecated correspondant à l’ancien rendu.
  • Tester la mise à jour sur une copie de la base contenant des articles réels, pas uniquement sur un site vide.
  • Ajouter un test avec @wordpress/scripts qui compare le rendu HTML du bloc à un instantané figé, pour détecter tout changement involontaire avant publication.
  • Documenter dans le changelog de l’extension chaque modification touchant à la structure du HTML sauvegardé.

En résumé

« Block validation failed » n’indique jamais une corruption de données : c’est un contrôle de cohérence qui fait exactement son travail, à savoir signaler qu’un bloc ne sait plus reproduire le rendu qu’il a lui-même généré auparavant. La correction passe presque toujours par une entrée deprecated bien ciblée, rarement par une restauration de sauvegarde.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

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

Voir tous ses articles

Dans la même veine

À lire aussi