yaml-cpp accepte silencieusement les clés dupliquées dans les mappings YAML et ne conserve que la dernière valeur : aucune erreur, aucun avertissement, aucune indication que les valeurs précédentes ont été écartées. La spécification YAML qualifie explicitement ce comportement d’indéfini, mais chaque analyseur majeur fait son propre choix. Ce guide explique ce que fait yaml-cpp, comment les autres analyseurs diffèrent, quels scénarios concrets produisent des doublons et comment les détecter avant qu’ils ne provoquent des pertes de données silencieuses en production.
Que sont les clés dupliquées en YAML ?
Une clé dupliquée apparaît lorsque la même chaîne de clé est présente plusieurs fois au même niveau dans un même mapping YAML. Dans un langage comme JSON, c’est tout aussi indéfini, mais visuellement évident. En YAML, où les mappings s’étendent sur plusieurs lignes et où les fichiers peuvent compter des centaines de lignes, les clés dupliquées sont faciles à introduire par accident et tout aussi faciles à manquer lors d’une relecture.
À quoi ressemble un doublon
La forme la plus simple est une répétition directe : une clé définie en haut d’un mapping et redéfinie plus bas, parfois avec une valeur différente. Cela se produit le plus souvent à cause d’erreurs de copier-coller, de refactorisations incomplètes ou de la fusion d’extraits de configuration de sources différentes. Les noms de clés sont identiques octet pour octet — même casse, même espacement — et apparaissent simplement deux fois dans le même bloc de mapping.
- Erreur de copier-coller : un bloc de clés est dupliqué lors de l’ajout d’une nouvelle section copiée d’une section existante
- Renommage incomplet : une clé est renommée mais l’originale n’est pas supprimée, les deux restant dans le fichier
- Fusion de configurations : deux fragments YAML sont concaténés et définissent tous deux la même clé de premier niveau
- Annulation de commentaire : une clé commentée est décommentée sans supprimer le remplacement actif situé en dessous
- Expansion de gabarit : un générateur ou un moteur de gabarits émet la même clé deux fois depuis des branches conditionnelles différentes
Remarque
Ce que dit réellement la spécification YAML
La spécification YAML 1.2 traite les clés dupliquées de façon directe et sans ambiguïté : elles ne sont pas autorisées dans un mapping YAML valide. La section 3.2.1.3 indique que les clés d’un mapping doivent être uniques au sein de ce mapping. Tout document contenant des clés dupliquées est techniquement non conforme.
Le contenu d’un nœud de mapping est un ensemble non ordonné de paires de nœuds clé/valeur, avec la restriction que chacune des clés est unique.
Indéfini ne signifie pas analyse invalide
La nuance essentielle est que, si la spécification qualifie les clés dupliquées de non conformes, elle n’impose pas aux analyseurs de les rejeter par une erreur bloquante. Elle décrit plutôt le comportement comme indéfini, ce qui signifie que chaque implémentation d’analyseur est libre de traiter les doublons comme elle l’entend. C’est pourquoi yaml-cpp, PyYAML, js-yaml et d’autres acceptent tous les doublons sans lever d’exception, même si le document obtenu est techniquement du YAML invalide.
Pourquoi cela compte en pratique
Un « comportement indéfini » dans une spécification signifie que votre application s’appuie sur un détail d’implémentation qui peut changer d’une version de bibliothèque à l’autre. yaml-cpp utilise actuellement « la dernière valeur gagne », mais rien dans la spécification ne le garantit. Une version future pourrait passer à « la première valeur gagne », lever une exception ou renvoyer un nœud d’erreur, et chacun de ces changements resterait conforme à la spécification. Un code qui dépend accidentellement du comportement de résolution des clés dupliquées est fragile par définition.
Avertissement
Le comportement de yaml-cpp en détail
yaml-cpp est la bibliothèque d’analyse YAML pour C++ la plus utilisée et le choix par défaut de nombreuses applications C++ et moteurs de jeu. Lorsque yaml-cpp rencontre une clé dupliquée dans un mapping, il analyse les deux occurrences mais ne conserve que la dernière dans l’arbre Node résultant. La valeur précédente est écrasée et définitivement absente de la structure analysée.
La règle « la dernière valeur gagne »
Dans l’implémentation de yaml-cpp, chaque clé d’un mapping est stockée dans une liste ordonnée de paires clé-valeur. Lorsqu’une clé dupliquée est analysée, yaml-cpp recherche dans la liste existante une clé correspondante. Si elle est trouvée, la valeur stockée est remplacée par la nouvelle. Le nœud de la valeur précédente est libéré. Du point de vue de l’application, interroger `node["key"]` renvoie la dernière valeur définie comme s’il n’y avait jamais eu qu’une seule définition.
Aucune sortie de diagnostic par défaut
yaml-cpp n’émet aucun avertissement, message de journal ni exception lorsqu’il écrase une clé dupliquée. L’analyse réussit avec un `YAML::Node` qui semble parfaitement normal. Aucun indicateur ne permet, après analyse, de découvrir que des doublons ont été résolus silencieusement. Le seul moyen de les détecter est d’examiner le texte brut avant l’analyse — exactement ce que fait un détecteur dédié de clés dupliquées.
Un comportement cohérent quel que soit le style de mapping
yaml-cpp applique « la dernière valeur gagne » de façon cohérente, que le mapping utilise le style bloc (clés sur des lignes séparées) ou le style flux avec accolades. Les mappings imbriqués sont traités indépendamment : les doublons ne sont comparés qu’au sein du même niveau de mapping, pas dans tout l’arbre du document. Une clé présente dans deux mappings frères à des profondeurs d’imbrication différentes n’est pas considérée comme un doublon.
Détecteur de clés dupliquées YAML
Collez votre document YAML et trouvez instantanément toutes les clés dupliquées à chaque niveau d’imbrication : numéros de ligne et les deux valeurs concurrentes sont signalés pour que vous les corrigiez avant qu’elles n’atteignent yaml-cpp.
Comment les autres analyseurs traitent les doublons
La spécification YAML laissant indéfini le comportement des clés dupliquées, chaque écosystème d’analyseur a pris sa propre décision. Les différences entre langages sont suffisamment importantes pour qu’un fichier YAML qui passe silencieusement dans un pipeline échoue durement dans un autre. Comprendre le paysage vous aide à écrire du YAML portable.
| Analyseur / Bibliothèque | Langage | Comportement sur clé dupliquée |
|---|---|---|
| yaml-cpp | C++ | La dernière valeur gagne : silencieux, aucun avertissement |
| PyYAML | Python | La dernière valeur gagne : silencieux, aucun avertissement |
| ruamel.yaml (strict) | Python | Lève DuplicateKeyError si configuré |
| js-yaml | JavaScript | La dernière valeur gagne : silencieux, aucun avertissement |
| gopkg.in/yaml.v3 | Go | Renvoie une erreur : duplicate map key |
| go-yaml v2 | Go | La dernière valeur gagne : silencieux, aucun avertissement |
| Psych (par défaut) | Ruby | Lève Psych::BadAlias / erreur dans les versions récentes |
| SnakeYAML | Java | La dernière valeur gagne : silencieux (configurable) |
| YamlDotNet | C# / .NET | La dernière valeur gagne : silencieux, aucun avertissement |
| libfyaml | C | Émet un avertissement ; comportement configurable |
La conclusion pratique est nette : `yaml.v3` de Go traite les doublons comme des erreurs bloquantes, tandis que yaml-cpp, PyYAML et js-yaml les acceptent silencieusement. Un fichier de configuration YAML qui fonctionne dans votre application C++ avec yaml-cpp peut échouer immédiatement lorsque le même fichier est traité par un service Go ou un linter Python strict dans un pipeline CI.
Astuce
Scénarios concrets qui produisent des doublons
La plupart des clés dupliquées ne sont pas intentionnelles. Elles apparaissent selon des schémas prévisibles dans la façon dont les développeurs écrivent et maintiennent les fichiers de configuration YAML. Connaître les causes fréquentes vous aide à les repérer à la source.
Croissance du fichier de configuration dans le temps
Les fichiers de configuration durables accumulent les modifications de nombreux contributeurs. Une clé définie il y a des mois près du début du fichier est redéfinie par un nouveau contributeur qui ignorait qu’elle existait déjà. C’est particulièrement fréquent dans les fichiers `values.yaml` de Helm, les ConfigMaps Kubernetes et les fichiers de variables Ansible, où des centaines de clés peuvent être réparties dans un fichier trop long pour être relu intégralement.
Fusion de fragments de configuration venant d’équipes différentes
Lorsque deux équipes indépendantes ou microservices contribuent à une configuration YAML partagée, la même clé de premier niveau peut être définie par les deux. Le fichier fusionné final contient les deux définitions, et celle qui apparaît en dernier gagne silencieusement. C’est une source fréquente de bugs de surcharge propres à un environnement, où la valeur de la mauvaise équipe s’applique en production.
Le schéma « commenter puis remplacer »
Un développeur commente `timeout: 30` et ajoute `timeout: 60` juste en dessous comme remplacement. Plus tard, quelqu’un retire les caractères de commentaire de l’ancienne ligne — peut-être lors d’un rechercher-remplacer global ou à cause d’un formateur d’éditeur mal configuré — et les deux valeurs deviennent actives. La dernière gagne, mais laquelle est la dernière dépend de la position de chaque ligne dans le fichier.
Bugs de gabarit ou de génération de code
Les pipelines CI/CD et les outils d’infrastructure as code génèrent souvent du YAML par programme. Un bug dans la logique du gabarit — une branche conditionnelle qui n’exclut pas correctement une clé déjà émise par une autre branche — peut produire du YAML d’apparence valide avec des doublons silencieux. Le fichier généré passe l’analyse yaml-cpp, et la mauvaise valeur est utilisée en production sans qu’aucune erreur ne soit journalisée.
Avertissement
Détecter et prévenir les doublons
Les clés dupliquées sont simples à détecter avec les bons outils. Le défi est de les repérer avant qu’elles n’atteignent un analyseur de production, et non après que la perte de données silencieuse s’est produite. Le flux de travail suivant couvre la détection à chaque étape, de la rédaction au déploiement.
Étape 1 : détection avant commit avec le détecteur de clés dupliquées YAML
Le détecteur de clés dupliquées YAML analyse l’intégralité de votre document YAML — y compris les mappings imbriqués à toute profondeur — et signale chaque clé dupliquée avec ses numéros de ligne ainsi que la valeur écrasée et la valeur survivante. Collez votre fichier avant de committer pour repérer les problèmes instantanément. Aucun envoi, aucune inscription, et le fichier ne quitte jamais votre navigateur.
Étape 2 : linting dans l’éditeur avec yamllint
Pour les équipes qui manipulent quotidiennement des fichiers YAML, `yamllint` avec la règle `key-duplicates` réglée sur `enable` détecte les doublons à chaque enregistrement. Les utilisateurs de VS Code peuvent installer l’extension YAML (Red Hat), qui intègre automatiquement yamllint. Ajouter yamllint à vos hooks de pré-commit et à votre pipeline CI garantit que les doublons n’atteignent jamais une relecture de code où ils pourraient passer inaperçus.
Étape 3 : analyse en mode strict dans votre suite de tests
Même si votre code de production utilise yaml-cpp, vous pouvez ajouter une passe de validation au moment des tests avec un analyseur strict. Analysez chaque fichier de configuration YAML avec `yaml.v3` de Go ou ruamel.yaml de Python en mode strict dans le cadre de votre suite de tests. Ces analyseurs échouent sur les doublons, ce qui vous donne un échec de test net au lieu d’un bug silencieux à l’exécution. Après vos vérifications de doublons, utilisez le validateur d’ancres et d’alias YAML pour confirmer également que l’usage de vos ancres et alias est propre.
Détecteur de clés dupliquées YAML
Trouvez instantanément toutes les clés dupliquées dans n’importe quel document YAML : chaque niveau d’imbrication est analysé, les numéros de ligne sont signalés et les deux valeurs sont affichées côte à côte.
Prévention : bonnes pratiques structurelles
- Triez les clés par ordre alphabétique : l’ordre alphabétique rend la détection des doublons triviale lors de la relecture du code
- Utilisez des ancres YAML pour les valeurs partagées : au lieu de dupliquer un bloc, définissez une ancre une fois et référencez-la par un alias
- Imposez yamllint dans la CI : un pipeline qui échoue est un signal bien plus fort qu’un commentaire de relecture
- Relisez les gros diffs de configuration globalement : consultez la vue complète du fichier, pas seulement les lignes modifiées, lors de la relecture de changements de configuration
- Gardez les fichiers courts : découpez les gros fichiers de configuration en sous-fichiers ciblés pour réduire la surface des doublons
Clés de fusion, ancres et pièges associés
La clé de fusion YAML (`<<`) et le système d’ancres/alias sont les mécanismes légitimes de réutilisation de valeurs dans un document. Comprendre leur interaction avec la détection de clés dupliquées évite les faux positifs dans vos outils et vous aide à les utiliser en toute sécurité.
Comment fonctionnent les clés de fusion
La clé de fusion `<<` demande à un analyseur YAML d’incorporer les paires clé-valeur d’un mapping ancré dans le mapping courant. Ce n’est pas une clé dupliquée : `<<` est un indicateur réservé dans la spécification YAML 1.1 et une extension largement prise en charge en 1.2. Lorsqu’une clé de fusion importe une clé déjà présente dans le mapping cible, la définition explicite du mapping cible prime sur la valeur fusionnée. C’est un comportement intentionnel et prévisible, contrairement aux clés dupliquées accidentelles.
Ancres et détection des doublons
Les ancres YAML (`&name`) et les alias (`*name`) ne sont pas des doublons. Une ancre définit un nœud réutilisable ; un alias le référence. Les deux peuvent apparaître de nombreuses fois dans un document sans créer de violation de clé dupliquée. Le validateur d’ancres et d’alias YAML vérifie spécifiquement que chaque alias se résout vers une ancre déclarée et qu’il n’existe pas de références circulaires — des problèmes distincts des clés dupliquées.
Quand les clés de fusion produisent des doublons apparents
Une clé de fusion peut créer ce qui ressemble à un doublon si le mapping de base ancré et le mapping cible définissent tous deux la même clé. Ce n’est pas un bug : la spécification définit que les clés explicites priment sur les clés fusionnées. Toutefois, certains linters de clés dupliquées le signalent comme une erreur. Si vous voyez des faux positifs dans yamllint pour des configurations basées sur `<<`, vérifiez que vous utilisez correctement les clés de fusion avant de masquer l’avertissement. Pour les fichiers `values.yaml` Helm complexes qui utilisent beaucoup d’ancres, comparer les versions avec le surligneur de différences pour configurations JSON/YAML facilite le repérage des changements au niveau des clés dans les pull requests.
Remarque
Points clés
- yaml-cpp applique la dernière valeur gagne pour les clés dupliquées : les valeurs précédentes sont écrasées silencieusement, sans erreur ni avertissement.
- La spécification YAML 1.2 indique explicitement que les clés dupliquées ne sont pas autorisées et qualifie ce comportement d’indéfini.
- Le comportement varie fortement selon les analyseurs : `yaml.v3` de Go échoue sur les doublons, tandis que PyYAML et js-yaml conservent silencieusement la dernière valeur comme yaml-cpp.
- Les clés critiques pour la sécurité comme `admin` ou `enabled` sont les cibles les plus dangereuses : un doublon peut accorder ou révoquer un accès de façon invisible.
- Utilisez le détecteur de clés dupliquées YAML pour analyser n’importe quel fichier YAML et trouver les doublons à chaque niveau d’imbrication avant le déploiement.
- Ajoutez `yamllint` avec `key-duplicates: enable` à votre pipeline CI pour une prévention automatique à chaque commit.
- Les clés de fusion YAML (`<<`) et les ancres ne sont pas des doublons : ce sont des mécanismes de réutilisation intentionnels avec des règles de priorité définies.