# « 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.

- Auteur : WordPress Développement
- Publié le : 2020-09-13
- Mis à jour le : 2020-09-13
- Catégorie : Blocs Gutenberg
- URL : https://www.wpmoderne.fr/blocs/erreur-block-validation-failed-apres-maj-mineure/

## L’essentiel

- 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

« 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.
