Saltar al contenido
Aback Tools Logo

Comportamiento de yaml-cpp con claves duplicadas explicado

yaml-cpp acepta en silencio las claves duplicadas en los mapeos YAML y conserva solo el último valor: sin error, sin advertencia, sin ninguna indicación de que los valores anteriores se descartaron. Esta guía explica qué hace yaml-cpp, en qué se diferencian otros analizadores, qué escenarios reales producen duplicados y cómo detectarlos antes de que provoquen errores silenciosos de pérdida de datos en producción.

DH
Tutorials & How-Tos12 min de lectura2,700 palabras

yaml-cpp acepta en silencio las claves duplicadas en los mapeos YAML y conserva solo el último valor: sin error, sin advertencia, sin ninguna indicación de que los valores anteriores se descartaron. La especificación YAML llama explícitamente indefinido a este comportamiento, pero cada analizador importante toma su propia decisión. Esta guía explica qué hace yaml-cpp, en qué se diferencian otros analizadores, qué escenarios reales producen duplicados y cómo detectarlos antes de que provoquen errores silenciosos de pérdida de datos en producción.

ÚltimoGana el valorLos valores anteriores se pierden en silencio
0Errores por defectoyaml-cpp no avisa de nada
Indef.Dice la especificaciónYAML 1.2 lo llama indefinido

¿Qué son las claves duplicadas en YAML?

Una clave duplicada se produce cuando la misma cadena de clave aparece más de una vez en el mismo nivel dentro de un único mapeo YAML. En un lenguaje como JSON esto también está indefinido, pero es visualmente obvio. En YAML, donde los mapeos abarcan varias líneas y los archivos pueden tener cientos de líneas, las claves duplicadas son fáciles de introducir por accidente y igual de fáciles de pasar por alto en una revisión.

Cómo se ve un duplicado

La forma más simple es una repetición directa: una clave definida al principio de un mapeo y redefinida más abajo, a veces con un valor diferente. Esto ocurre sobre todo por errores de copiar y pegar, refactorizaciones incompletas o la fusión de fragmentos de configuración de distintas fuentes. Los nombres de clave son idénticos byte a byte (misma capitalización, mismos espacios) y simplemente aparecen dos veces en el mismo bloque de mapeo.

  • Error de copiar y pegar: se duplica un bloque de claves al añadir una sección nueva basada en una existente
  • Renombrado incompleto: se renombra una clave pero no se elimina la original, y ambas quedan en el archivo
  • Fusión de configuraciones: se concatenan dos fragmentos YAML y ambos definen la misma clave de nivel superior
  • Reversión de comentario: se descomenta una clave sin eliminar el reemplazo activo que está debajo
  • Expansión de plantillas: un generador o motor de plantillas emite la misma clave dos veces desde ramas condicionales distintas

Nota

Las claves duplicadas en niveles de anidamiento distintos no son duplicados: `database.host` y `cache.host` son claves totalmente separadas aunque ambas usen `host` como nombre local. La regla de claves duplicadas se aplica solo dentro de un mismo bloque de mapeo, no en todo el documento.

Qué dice realmente la especificación YAML

La especificación YAML 1.2 aborda las claves duplicadas de forma directa e inequívoca: no están permitidas en un mapeo YAML válido. La sección 3.2.1.3 indica que las claves de un mapeo deben ser únicas dentro de ese mapeo. Cualquier documento con claves duplicadas es técnicamente no conforme.

El contenido de un nodo de mapeo es un conjunto no ordenado de pares de nodos clave/valor, con la restricción de que cada una de las claves sea única.

- Especificación YAML 1.2, sección 3.2.1.3

Indefinido no significa análisis inválido

El matiz crítico es que, aunque la especificación considera las claves duplicadas no conformes, no obliga a que los analizadores las rechacen con un error grave. En su lugar, describe el comportamiento como indefinido, lo que significa que cada implementación de analizador es libre de tratar los duplicados como quiera. Por eso yaml-cpp, PyYAML, js-yaml y otros analizadores aceptan duplicados sin lanzar nada, aunque el documento resultante sea técnicamente YAML inválido.

Por qué esto importa en la práctica

Un «comportamiento indefinido» en una especificación significa que tu aplicación depende de un detalle de implementación que podría cambiar entre versiones de la biblioteca. Actualmente yaml-cpp usa «gana el último valor», pero nada en la especificación lo garantiza. Una versión futura podría pasar a «gana el primer valor», lanzar una excepción o devolver un nodo de error, y cualquiera de esos cambios sería conforme a la especificación. El código que depende por accidente del comportamiento de resolución de claves duplicadas es frágil por definición.

Aviso

Si tu aplicación escribe deliberadamente YAML con claves duplicadas esperando un comportamiento de resolución concreto, ese código depende de un comportamiento indefinido de la especificación YAML. Cualquier actualización del analizador podría romperlo en silencio. Elimina los duplicados y expresa la intención con una estructura explícita.

El comportamiento de yaml-cpp en detalle

yaml-cpp es la biblioteca de análisis YAML para C++ más usada y la opción predeterminada en muchas aplicaciones C++ y motores de videojuegos. Cuando yaml-cpp encuentra una clave duplicada en un mapeo, analiza ambas apariciones pero solo conserva la última en el árbol Node resultante. El valor anterior se sobrescribe y desaparece definitivamente de la estructura analizada.

La regla de «gana el último valor»

En la implementación de yaml-cpp, cada clave de un mapeo se guarda en una lista ordenada de pares clave-valor. Cuando se analiza una clave duplicada, yaml-cpp busca en la lista existente una clave coincidente. Si la encuentra, sustituye el valor almacenado por el nuevo. El nodo del valor anterior se libera. Desde la perspectiva de la aplicación, consultar `node["key"]` devuelve el último valor definido como si solo hubiera existido una definición.

Sin salida de diagnóstico por defecto

yaml-cpp no emite ninguna advertencia, mensaje de registro ni excepción cuando sobrescribe una clave duplicada. El análisis finaliza con un `YAML::Node` que parece completamente normal. No hay ninguna marca que puedas consultar después del análisis para descubrir que se resolvieron duplicados en silencio. La única forma de detectarlos es revisar el texto sin procesar antes de analizarlo, que es exactamente lo que hace un detector dedicado de claves duplicadas.

El comportamiento es coherente entre estilos de mapeo

yaml-cpp aplica «gana el último valor» de forma coherente, independientemente de si el mapeo usa estilo de bloque (claves en líneas separadas) o estilo de flujo con llaves. Los mapeos anidados se gestionan de forma independiente: los duplicados solo se comparan dentro del mismo nivel de mapeo, no en todo el árbol del documento. Una clave que aparece en dos mapeos hermanos a distinta profundidad de anidamiento no se considera duplicada.

Detector de claves duplicadas en YAML

Pega tu documento YAML y encuentra al instante todas las claves duplicadas en cada nivel de anidamiento: informa de los números de línea y de ambos valores en conflicto para que los corrijas antes de que lleguen a yaml-cpp.

Open tool

Cómo tratan los duplicados otros analizadores

Como la especificación YAML deja indefinido el comportamiento con claves duplicadas, cada ecosistema de analizadores ha tomado su propia decisión. La variación entre lenguajes es lo bastante grande como para que un archivo YAML que pasa en silencio en una canalización falle sin remedio en otra. Conocer el panorama te ayuda a escribir YAML portátil.

Analizador / BibliotecaLenguajeComportamiento con claves duplicadas
yaml-cppC++Gana el último valor: silencioso, sin advertencia
PyYAMLPythonGana el último valor: silencioso, sin advertencia
ruamel.yaml (estricto)PythonLanza DuplicateKeyError cuando se configura
js-yamlJavaScriptGana el último valor: silencioso, sin advertencia
gopkg.in/yaml.v3GoDevuelve error: duplicate map key
go-yaml v2GoGana el último valor: silencioso, sin advertencia
Psych (por defecto)RubyLanza Psych::BadAlias / error en versiones recientes
SnakeYAMLJavaGana el último valor: silencioso (configurable)
YamlDotNetC# / .NETGana el último valor: silencioso, sin advertencia
libfyamlCEmite advertencia; comportamiento configurable

La conclusión práctica es contundente: `yaml.v3` de Go trata los duplicados como errores graves, mientras que yaml-cpp, PyYAML y js-yaml los aceptan en silencio. Un archivo de configuración YAML que funciona en tu aplicación C++ con yaml-cpp puede fallar de inmediato cuando el mismo archivo lo procesa un servicio Go o un linter estricto de Python en una canalización de CI.

Consejo

Usa el [Validador de YAML](/tools/data/validators/yaml-validator) para comprobar tus archivos YAML contra la especificación antes de confirmarlos. Para lograr portabilidad entre lenguajes, trata cualquier archivo con claves duplicadas como roto, aunque tu analizador concreto lo acepte en silencio hoy.

Escenarios reales que provocan duplicados

La mayoría de las claves duplicadas no son intencionadas. Aparecen por patrones previsibles en cómo los desarrolladores escriben y mantienen los archivos de configuración YAML. Conocer las causas habituales te ayuda a detectarlas en el origen.

1

Crecimiento del archivo de configuración con el tiempo

Los archivos de configuración longevos acumulan cambios de muchos colaboradores. Una clave definida hace meses cerca del principio del archivo la redefine un nuevo colaborador que no se dio cuenta de que ya existía. Es especialmente común en archivos `values.yaml` de Helm, ConfigMaps de Kubernetes y archivos de variables de Ansible, donde cientos de claves pueden repartirse en un archivo demasiado largo para revisarlo entero.

2

Fusionar fragmentos de configuración de distintos equipos

Cuando dos equipos independientes o microservicios contribuyen a una configuración YAML compartida, la misma clave de nivel superior puede estar definida por ambos. El archivo fusionado final contiene las dos definiciones y, silenciosamente, gana la que aparece en último lugar. Es una fuente habitual de errores de anulación específicos de entorno en los que el valor del equipo equivocado se aplica en producción.

3

Patrón de comentar y reemplazar

Un desarrollador comenta `timeout: 30` y añade `timeout: 60` justo debajo como reemplazo. Más tarde, alguien quita los caracteres de comentario de la línea antigua, quizá en un buscar y reemplazar global o con un formateador mal configurado, y ambos valores quedan activos. Gana el último, pero cuál es el último depende de dónde quedó cada línea en el archivo.

4

Errores de plantillas o generación de código

Las canalizaciones de CI/CD y las herramientas de infraestructura como código suelen generar YAML de forma programática. Un error en la lógica de la plantilla, como una rama condicional que no excluye correctamente una clave ya emitida por otra rama, puede producir YAML de aspecto válido con duplicados silenciosos. El archivo generado pasa el análisis de yaml-cpp y el valor equivocado se usa en producción sin registrar ningún error.

Aviso

Los duplicados más peligrosos están en claves críticas para la seguridad: `admin`, `enabled`, `role`, `permissions`. Como yaml-cpp acepta duplicados en silencio, una configuración con `admin: false` seguida de `admin: true` concede acceso de administrador mientras sigue mostrando `false` a cualquiera que lea el archivo de forma lineal. Ejecuta el [Detector de claves duplicadas en YAML](/tools/data/validators/yaml-duplicate-key-detector) en cada archivo de configuración relacionado con la seguridad antes del despliegue.

Detectar y prevenir duplicados

Detectar claves duplicadas es sencillo con las herramientas adecuadas. El reto es atraparlas antes de que lleguen a un analizador de producción, no después de que ya se haya producido la pérdida silenciosa de datos. Este flujo de trabajo cubre la detección en todas las etapas, desde la escritura hasta el despliegue.

Paso 1: detección previa a la confirmación con el Detector de claves duplicadas en YAML

El Detector de claves duplicadas en YAML analiza todo tu documento YAML, incluidos los mapeos anidados a cualquier profundidad, y reporta cada clave duplicada con sus números de línea y tanto el valor sobrescrito como el superviviente. Pega tu archivo antes de confirmar para detectar problemas al instante. Sin subidas, sin registro y el archivo nunca sale de tu navegador.

Paso 2: linting en el editor con yamllint

Para equipos que trabajan a diario con archivos YAML, `yamllint` con la regla `key-duplicates` en `enable` detecta duplicados en cada guardado. Los usuarios de VS Code pueden instalar la extensión YAML (Red Hat), que integra yamllint automáticamente. Añadir yamllint a tus hooks previos a la confirmación y a tu canalización de CI hace que los duplicados nunca lleguen a una revisión de código donde podrían pasarse por alto.

Paso 3: análisis en modo estricto en tu suite de pruebas

Aunque tu código de producción use yaml-cpp, puedes añadir una validación en tiempo de prueba con un analizador estricto. Analiza cada archivo de configuración YAML con `yaml.v3` de Go o ruamel.yaml de Python en modo estricto como parte de tu suite de pruebas. Estos analizadores dan error con duplicados, lo que te proporciona un fallo de prueba contundente en lugar de un error silencioso en tiempo de ejecución. Después de ejecutar tus comprobaciones de duplicados, usa el Validador de anclas y alias de YAML para confirmar también que el uso de anclas y alias está limpio.

Detector de claves duplicadas en YAML

Encuentra al instante todas las claves duplicadas en cualquier documento YAML: se analiza cada nivel de anidamiento, se informan los números de línea y se muestran ambos valores en paralelo.

Open tool

Prevención: buenas prácticas estructurales

  • Ordena las claves alfabéticamente: el orden alfabético hace trivial detectar duplicados durante la revisión de código
  • Usa anclas de YAML para valores compartidos: en lugar de duplicar un bloque, define un ancla una vez y referénciala con un alias
  • Aplica yamllint en CI: una canalización que falla es una señal mucho más fuerte que un comentario en la revisión de código
  • Revisa los diff grandes de configuración en conjunto: revisa la vista completa del archivo, no solo las líneas cambiadas, al revisar cambios de configuración
  • Mantén los archivos cortos: divide los archivos de configuración grandes en subarchivos enfocados para reducir la superficie de duplicados

Claves de fusión, anclas y otras trampas

La clave de fusión de YAML (`<<`) y el sistema de anclas y alias son los mecanismos legítimos para reutilizar valores en un documento. Entender cómo interactúan con la detección de claves duplicadas evita falsos positivos en tus herramientas y te ayuda a usarlos con seguridad.

Cómo funcionan las claves de fusión

La clave de fusión `<<` indica a un analizador YAML que incorpore los pares clave-valor de un mapeo anclado al mapeo actual. No es una clave duplicada: `<<` es un indicador reservado en la especificación YAML 1.1 y una extensión ampliamente soportada en 1.2. Cuando una clave de fusión importa una clave que ya existe en el mapeo destino, la definición explícita del destino tiene prioridad sobre el valor fusionado. Es un comportamiento intencionado y predecible, a diferencia de las claves duplicadas accidentales.

Anclas y detección de duplicados

Las anclas de YAML (`&name`) y los alias (`*name`) no son duplicados. Un ancla define un nodo reutilizable y un alias lo referencia. Ambos pueden aparecer muchas veces en un documento sin crear una violación de claves duplicadas. El Validador de anclas y alias de YAML comprueba específicamente que cada alias se resuelve a un ancla declarada y que no hay referencias circulares, problemas distintos de las claves duplicadas.

Cuándo las claves de fusión producen duplicados aparentes

Una clave de fusión puede crear lo que parece un duplicado si el mapeo base anclado y el mapeo destino definen la misma clave. No es un error: la especificación define que las claves explícitas tienen prioridad sobre las claves fusionadas. Sin embargo, algunos linters de claves duplicadas lo reportan como error. Si ves falsos positivos en yamllint con configuraciones basadas en `<<`, confirma que estás usando bien las claves de fusión antes de silenciar la advertencia. Para archivos `values.yaml` de Helm complejos que usan mucho las anclas, comparar versiones con el Resaltador de diferencias para configuraciones JSON/YAML facilita detectar cambios a nivel de clave en las solicitudes de extracción.

Nota

yaml-cpp admite claves de fusión cuando se usa la función `YAML::LoadAll` o `YAML::Load` con documentos YAML 1.1. Si usas yaml-cpp con modo estricto YAML 1.2, es posible que las claves de fusión no se procesen. Revisa tu versión de yaml-cpp y la declaración de versión del documento (`%YAML 1.2`) si las claves de fusión parecen ignorarse.

Puntos clave

  • yaml-cpp usa gana el último valor con las claves duplicadas: los valores anteriores se sobrescriben en silencio, sin error ni advertencia.
  • La especificación YAML 1.2 dice explícitamente que las claves duplicadas no están permitidas y describe el comportamiento como indefinido.
  • El comportamiento varía mucho entre analizadores: `yaml.v3` de Go da error con duplicados, mientras que PyYAML y js-yaml conservan el último valor en silencio como yaml-cpp.
  • Las claves críticas para la seguridad como `admin` o `enabled` son los objetivos más peligrosos: un duplicado puede conceder o revocar acceso de forma invisible.
  • Usa el Detector de claves duplicadas en YAML para analizar cualquier archivo YAML y encontrar duplicados en cada nivel de anidamiento antes del despliegue.
  • Añade `yamllint` con `key-duplicates: enable` a tu canalización de CI para prevención automática en cada confirmación.
  • Las claves de fusión de YAML (`<<`) y las anclas no son duplicados: son mecanismos de reutilización intencionados con reglas de prioridad definidas.

Preguntas frecuentes

yaml-cpp usa la semántica de «gana el último valor» al analizar un mapeo YAML con claves duplicadas. Si la misma clave aparece más de una vez en el mismo nivel de mapeo, el analizador sobrescribe el valor anterior con el posterior y, de forma predeterminada, no emite ningún error ni advertencia. El objeto Node resultante en memoria contiene solo el valor final y todos los anteriores se descartan en silencio. Esto coincide con el comportamiento de muchos otros analizadores YAML, pero técnicamente la especificación YAML lo deja sin definir.

No: la especificación YAML 1.2 afirma que las claves duplicadas en un mapeo «no están permitidas» y describe explícitamente el comportamiento como indefinido. Sin embargo, no exige que los analizadores lancen un error; solo dice que el resultado no está especificado. La mayoría de los analizadores, incluido yaml-cpp, optan por aceptar los duplicados en silencio en lugar de detener el análisis, lo que convierte las claves duplicadas en una fuente de errores silenciosos de pérdida de datos en lugar de errores evidentes en tiempo de ejecución.

Cuando yaml-cpp encuentra una clave que ya ha visto en el mismo mapeo, sustituye el valor almacenado por el nuevo. El valor anterior se pierde definitivamente: no hay forma de recuperarlo después del análisis. Se llama «gana el último valor» porque la definición de la clave que aparece en último lugar en el documento es la que sobrevive. La regla se aplica de forma independiente en cada nivel de anidamiento.

El comportamiento varía según el analizador. PyYAML (Python) también usa «gana el último valor» en silencio de forma predeterminada, aunque ruamel.yaml puede configurarse para lanzar un error. gopkg.in/yaml.v3 de Go lanza un error con claves duplicadas. js-yaml de JavaScript conserva el último valor en silencio, sin advertencia. Psych de Ruby lanza un error. Esta inconsistencia entre analizadores significa que un archivo que parece válido en la cadena de herramientas de un lenguaje puede perder datos en silencio en otra.

La forma más rápida es pegar tu YAML en el Detector de claves duplicadas de Aback Tools, que analiza todo el documento, incluidos los mapeos anidados, y reporta todos los duplicados con números de línea y ambos valores en conflicto. Como alternativa, puedes usar un analizador estricto como gopkg.in/yaml.v3 en Go o ruamel.yaml en Python con la opción allow_duplicate_keys=False. Para canalizaciones de CI/CD, yamllint con la regla braces: {forbid-flow-sequences: true} y key-duplicates: enable detecta duplicados automáticamente en cada confirmación.

Sí, en determinados escenarios. Si un archivo YAML se usa para configuración de control de acceso o indicadores de funcionalidad, una clave duplicada puede sobrescribir en silencio un valor crítico para la seguridad. Por ejemplo, una clave como `admin: false` seguida más adelante por `admin: true` concedería acceso de administrador por la regla de «gana el último valor», mientras que la entrada `false` parece el valor efectivo para cualquiera que lea el archivo de arriba abajo. Esta clase de error ha aparecido en CVE reales relacionados con el análisis de archivos de configuración. La detección automática de duplicados es una salvaguarda de bajo coste.

Una clave duplicada es una repetición involuntaria o errónea del mismo nombre de clave dentro de un mapeo. Una clave de fusión de YAML (<<) es una característica estándar de YAML que incorpora deliberadamente el contenido de un ancla a un mapeo. La clave de fusión en sí no es un duplicado: es una clave especial con semántica definida. Sin embargo, si una clave de fusión introduce una clave que ya existe en el mapeo destino, la definición explícita tiene prioridad sobre el valor fusionado. Esto es intencionado y no un error de claves duplicadas.

En código de producción, sí. La API Node de yaml-cpp no expone de forma nativa una opción de modo estricto que dé error con duplicados, pero puedes implementar una validación posterior al análisis con el Detector de claves duplicadas o un recorrido personalizado que compruebe claves repetidas antes de que tu aplicación lea la configuración. Para archivos de configuración críticos, sobre todo de autenticación, seguridad e infraestructura, se recomienda encarecidamente una comprobación de claves duplicadas en tu canalización de CI. El Detector de claves duplicadas de Aback Tools está diseñado exactamente para este caso de uso.

ShareXLinkedIn