YAML es el formato preferido para configuración legible por humanos (Docker Compose, GitHub Actions, Kubernetes, Ansible) precisamente porque prescinde de llaves y comillas obligatorias, pero esa flexibilidad es también su principal fuente de errores silenciosos: la indentación con tabuladores está prohibida por la especificación **YAML 1.2**, los valores sin comillas se interpretan con tipos implícitos que sorprenden (el famoso «problema de Noruega»), y dos claves duplicadas en el mismo mapa no siempre producen un error visible. Un validador YAML no solo comprueba que el documento se pueda analizar (parsear); si usa reglas de estilo tipo `yamllint`, además detecta indentación inconsistente y advierte de valores ambiguos antes de que lleguen a producción. Si el mismo dato debe convertirse a JSON, conviene revisar después con el conversor JSON/YAML de este sitio.
Tabuladores: por qué YAML los prohíbe y qué error da cada parser
La especificación YAML exige que la indentación se haga exclusivamente con espacios; un tabulador se trata como un carácter de control no permitido en esa posición. Al analizar "clave: valor\n\tsub: otro\n" con PyYAML el error exacto es: while scanning for the next token / found character '\t' that cannot start any token / in "<unicode string>", line 2, column 1. La causa habitual es un editor configurado para insertar tabuladores reales en vez de espacios, o pegar código copiado de una terminal que preserva tabulaciones. La solución no es solo sustituir el tabulador por espacios, sino configurar el editor para que la tecla Tab inserte siempre espacios en ficheros .yml y .yaml.
El problema de Noruega: `NO` no es el país, es `false`
YAML 1.1 define un conjunto de literales booleanos implícitos que incluye y, n, yes, no, true, false, on, off, en cualquier combinación de mayúsculas y minúsculas. Esto significa que pais: NO no almacena la cadena "NO" (código ISO de Noruega) sino el booleano false; al cargar "pais: Noruega\nactivo: NO\n" con PyYAML el resultado real es {'pais': 'Noruega', 'activo': False}: la clave pais se libra porque "Noruega" no coincide con ningún literal booleano completo, pero activo: NO sí. YAML 1.2 (usado por librerías como ruamel.yaml en modo estricto) redujo esa lista a solo true/false, pero la mayoría de parsers en producción (PyYAML, muchos parsers de Go) siguen implementando YAML 1.1 por compatibilidad. La única forma fiable de evitarlo es entrecomillar cualquier código de país, estado o valor ambiguo: pais: "NO".
Indentación inconsistente entre hermanos del mismo nivel
A diferencia de JSON, en YAML la indentación define la estructura, así que dos claves que deberían ser hermanas en el mismo mapa deben empezar exactamente en la misma columna. Un bloque donde una clave usa dos espacios y la siguiente usa tres genera, según el parser, o bien un error de sintaxis (mapping values are not allowed in this context) o bien, peor, una anidación no intencionada donde la segunda clave termina como hija de la primera en vez de su hermana. yamllint, a diferencia de un parser puro, sí detecta y avisa de indentación inconsistente aunque el documento sea técnicamente parseable, con un mensaje del tipo wrong indentation: expected 2 but found 3 (indentation) y la línea exacta.
Claves duplicadas: por qué el parser no siempre avisa
La especificación YAML establece que las claves de un mapa deben ser únicas, pero muchos parsers no lo validan por defecto y simplemente sobrescriben el valor anterior con el último encontrado, sin ningún aviso. Un fichero con puerto: 8080 seguido más abajo, tras 30 líneas de configuración, de otro puerto: 9090 cargará silenciosamente con el valor 9090, sin ningún error, y el bug puede pasar desapercibido en revisión de código porque ambas líneas son individualmente válidas. yamllint con la regla key-duplicates activada sí detecta este caso y lo reporta como error, no como aviso.
Multilínea: bloque literal (`|`) frente a bloque plegado (`>`)
YAML ofrece dos formas de escribir cadenas multilínea que se confunden con frecuencia. El indicador | (literal) conserva los saltos de línea tal cual aparecen en el bloque; el indicador > (plegado) convierte cada salto de línea en un espacio, uniendo las líneas en un único párrafo salvo que haya una línea en blanco, que se conserva como salto real. Escribir un script de shell multilínea en un YAML de GitHub Actions con > en vez de | es un error habitual: el script se colapsa en una sola línea y falla al ejecutarse porque los comandos que deberían estar en líneas separadas terminan concatenados sin separador.
Anclas, alias y fusión (`&`, `*`, `<<`) para no repetir configuración
Una ancla (&nombre) marca un nodo para reutilizarlo después con un alias (*nombre), y la clave especial de fusión <<: *nombre incorpora todas las claves de un mapa ancla dentro de otro, permitiendo herencia de configuración sin duplicar bloques enteros: útil en Docker Compose para compartir variables de entorno entre varios servicios. El riesgo es que un alias mal referenciado (una ancla que no existe o un error tipográfico en el nombre) produce un error de referencia que algunos parsers reportan de forma poco clara, señalando la línea del alias y no la de la ancla ausente.
Documentos múltiples separados por `---`
Un mismo fichero YAML puede contener varios documentos independientes separados por una línea con tres guiones (---), y opcionalmente terminados con .... Es el mecanismo que usa Kubernetes para definir varios recursos (un Deployment y su Service) en un solo fichero manifest.yaml. Un validador que solo procese el primer documento del fichero puede dar una falsa sensación de que todo es correcto cuando el segundo o tercer documento contiene el error real; herramientas como yamllint o yq eval-all procesan todos los documentos del fichero, no solo el primero.
Salidas reales de ejemplo
$ python3 -c "import yaml; yaml.safe_load(open('bad.yml').read())"
yaml.scanner.ScannerError: while scanning for the next token
found character '\t' that cannot start any token
in "bad.yml", line 2, column 1PyYAML rechaza cualquier tabulador usado para indentar, señalando línea y columna exactas.
$ python3 -c "import yaml; print(yaml.safe_load('pais: Noruega\nactivo: NO\n'))"
{'pais': 'Noruega', 'activo': False}"NO" se interpreta como booleano False, no como la cadena del código de país.
$ yamllint config.yml
config.yml
12:5 error wrong indentation: expected 4 but found 5 (indentation)
20:1 warning missing document start "---" (document-start)El aviso incluye la línea, la columna y qué indentación se esperaba frente a la encontrada.
pais: Noruega
activo: "NO"
# Resultado tras cargar:
# {'pais': 'Noruega', 'activo': 'NO'}Entrecomillar el código de país evita la conversión implícita a booleano.
JSON frente a YAML: qué elegir según el caso
| Característica | JSON | YAML |
|---|---|---|
| Comentarios | No admite | Sí, con # |
| Comas finales | Error de sintaxis | No aplica (no usa comas entre líneas) |
| Tipos implícitos ambiguos (NO, YES, on) | No existen; todo es literal | Sí, riesgo del "problema de Noruega" |
| Legibilidad para configuración manual | Media (llaves y comillas obligatorias) | Alta (indentación, sin comillas obligatorias) |
| Ideal para | Intercambio entre programas, APIs | Configuración editada por humanos |
Ambos representan los mismos datos, pero difieren en legibilidad, comentarios y ambigüedad de tipos.
Casos de uso comunes
- Depurar un `docker-compose.yml` que Docker rechaza al arrancar los servicios.
- Revisar un workflow de GitHub Actions antes de hacer commit, evitando fallos de indentación en el pipeline de CI.
- Detectar valores booleanos implícitos no deseados en ficheros de configuración con países, códigos o abreviaturas.
- Validar manifiestos de Kubernetes con varios documentos en un mismo fichero.
- Enseñar la diferencia entre bloque literal y bloque plegado antes de escribir scripts multilínea en YAML.
Buenas prácticas
- Configura el editor para insertar siempre espacios, nunca tabuladores, en ficheros `.yml` y `.yaml`.
- Entrecomilla cualquier valor que pueda confundirse con un booleano o un número: códigos de país, versiones, IDs.
- Activa `yamllint` con la regla `key-duplicates` en el pipeline de CI para detectar claves repetidas antes del despliegue.
- Usa `|` para preservar saltos de línea reales (scripts) y `>` solo cuando el contenido deba unirse en un párrafo.
- Si el fichero tiene varios documentos, valida con una herramienta que los procese todos, no solo el primero.
- Mantén la indentación en 2 espacios de forma consistente en todo el repositorio para evitar errores al copiar bloques entre ficheros.