Mis à jour le 17 octobre 2026
PrestaShop : réparer l'arborescence des catégories (nleft / nright)
Erreur « CategoryConstraintException », produits disparus de leurs catégories, menu incohérent : comment réparer l'arborescence (nleft/nright) de PrestaShop, étape par étape.
Vous enregistrez une catégorie et PrestaShop affiche :
[PrestaShop\PrestaShop\Core\Domain\Category\Exception\CategoryConstraintException code 6]
Ou, en enregistrant un produit :
This product must be in the default category.
Ou encore des produits qui n'apparaissent plus dans leurs catégories, des sous-catégories au mauvais endroit, un menu incohérent… Dans la plupart des cas, c'est l'arborescence des catégories qui est cassée. Pas de panique : elle se répare.
Comment PrestaShop range ses catégories
Pour éviter des requêtes lentes sur les catalogues à plusieurs niveaux, PrestaShop enregistre son arbre de catégories sous forme d'intervalles : chaque catégorie reçoit une borne gauche (nleft) et une borne droite (nright) qui englobent toutes ses sous-catégories.
Pour cet arbre :
Accueil
├── Cat 1
├── Cat 2
│ ├── Sous-cat 21
│ └── Sous-cat 22
└── Cat 3
les intervalles sont :
| Catégorie | nleft | nright |
|---|---|---|
| Accueil | 1 | 12 |
| Cat 1 | 2 | 3 |
| Cat 2 | 4 | 9 |
| Sous-cat 21 | 5 | 6 |
| Sous-cat 22 | 7 | 8 |
| Cat 3 | 10 | 11 |
Trouver toutes les sous-catégories de Cat 2 ne demande qu'une requête : les catégories dont les bornes sont comprises entre 4 et 9. Et une catégorie sans enfant se reconnaît à nright - nleft = 1.
Pour aller plus loin sur cette technique : la représentation intervallaire des arborescences (nouvel onglet).
Comment l'arbre se casse
Presque toujours de l'extérieur :
- un import ou une synchronisation (ERP, logiciel de caisse, module d'import) qui crée ou déplace des catégories sans recalculer les bornes ;
- une catégorie supprimée ou modifiée directement dans la base de données ;
- une migration mal terminée.
Une seule catégorie supprimée en base suffit à fausser toutes les bornes qui la suivent. Sur un gros catalogue, impossible de corriger à la main.
Avant toute chose : sauvegardez la base de données
Les étapes suivantes modifient directement la base. Faites une sauvegarde complète (phpMyAdmin › Exporter, ou l'outil de votre hébergeur) et, si possible, testez d'abord sur une copie de la boutique.
Les requêtes ci-dessous utilisent le préfixe de tables ps_ : remplacez-le par le vôtre s'il est différent (il figure dans app/config/parameters.php, ou config/settings.inc.php en 1.6).
Étape 1 : repérer les catégories orphelines
Une catégorie orpheline a pour parent une catégorie qui n'existe plus. La reconstruction l'ignore, et elle continue de semer le désordre.
SELECT c.id_category, cl.name, c.id_parent
FROM ps_category c
LEFT JOIN ps_category p ON p.id_category = c.id_parent
LEFT JOIN ps_category_lang cl ON cl.id_category = c.id_category AND cl.id_lang = 1
WHERE c.id_parent > 0 AND p.id_category IS NULL;
Si la requête renvoie des lignes, le plus sûr est de rattacher ces catégories à l'Accueil (id 2 sur une boutique standard), plutôt que de les supprimer : vous les déplacerez ensuite depuis l'administration.
UPDATE ps_category c
LEFT JOIN ps_category p ON p.id_category = c.id_parent
SET c.id_parent = 2, c.level_depth = 2
WHERE c.id_parent > 0 AND p.id_category IS NULL;
Étape 2 : remettre les bornes à zéro
UPDATE ps_category SET nleft = 0, nright = 0;
Étape 3 : reconstruire l'arbre
PrestaShop sait recalculer tout l'arbre (Category::regenerateEntireNtree()), mais ne propose aucun bouton pour le faire. Le plus simple : un petit script temporaire.
- À la racine de la boutique, créez un fichier
reparer-categories.php:
<?php
// Script temporaire : SUPPRIMEZ-LE juste après utilisation.
require __DIR__ . '/config/config.inc.php';
if (Tools::getValue('cle') !== 'remplacez-par-un-mot-de-passe') {
header('HTTP/1.1 403 Forbidden');
exit('Accès refusé');
}
Category::regenerateEntireNtree();
echo 'Arborescence reconstruite.';
- Ouvrez
https://votre-boutique.fr/reparer-categories.php?cle=remplacez-par-un-mot-de-passe. - Le message « Arborescence reconstruite. » s'affiche.
- Supprimez le fichier : laissé en ligne, c'est une porte d'entrée.
- Videz le cache (Paramètres avancés › Performances › Vider le cache).
Étape 4 : vérifier
SELECT id_category, id_parent, nleft, nright
FROM ps_category
WHERE id_category > 1 AND (nleft = 0 OR nright = 0);
Aucune ligne : l'arbre est sain. Réessayez d'enregistrer votre catégorie ou votre produit.
En dernier recours : supprimer les catégories restées à zéro
Si des catégories restent à zéro et que vous êtes sûr qu'elles ne servent à rien, vous pouvez les supprimer avec leurs traductions et associations. Attention : leurs liens avec les produits disparaissent aussi. Vérifiez d'abord qu'aucun produit ne les utilise comme catégorie par défaut :
SELECT p.id_product, p.id_category_default
FROM ps_product p
JOIN ps_category c ON c.id_category = p.id_category_default
WHERE c.nleft = 0 AND c.nright = 0 AND c.id_category > 1;
Puis, sauvegarde faite :
DELETE a, b, c, d, e
FROM ps_category a
LEFT JOIN ps_category_group b ON b.id_category = a.id_category
LEFT JOIN ps_category_lang c ON c.id_category = a.id_category
LEFT JOIN ps_category_product d ON d.id_category = a.id_category
LEFT JOIN ps_category_shop e ON e.id_category = a.id_category
WHERE a.nleft = 0 AND a.nright = 0 AND a.id_category > 1;
Relancez ensuite l'étape 3.
Éviter que ça se reproduise
- Ne supprimez jamais une catégorie directement dans la base : passez par l'administration ou par l'API, qui recalculent l'arbre.
- Si un ERP ou un module d'import gère vos catégories, vérifiez qu'il appelle bien la reconstruction après chaque synchronisation.
Et pour éviter les autres mauvaises surprises d'une boutique mal entretenue, voyez les 7 erreurs PrestaShop qui coûtent cher.
L'arbre est réparé, mais la boutique a d'autres soucis ? Ou vous préférez ne pas toucher à la base vous-même ? Nous intervenons sur les boutiques PrestaShop en panne, de la 1.6 à la 9 : Notre agence PrestaShop.