El validador de sintaxis YAML de FormatArc mostrando errores con número de línea en el navegadorEl validador de sintaxis YAML de FormatArc mostrando errores con número de línea en el navegador
Autor: Equipo editorial de FormatArcPublicado: 2026-04-13Actualizado: 2026-09-05

Cómo arreglar "Forbidden Block Composed Value" en YAML

TL;DR — la sintaxis de YAML en un minuto

  • Usa solo espacios (nada de tabuladores). La indentación de 2 espacios es la convención de facto.
  • key: value necesita un espacio después de los dos puntos. key:value es una sola cadena.
  • Las listas usan - (guion + espacio). Los mapeos usan key: value.
  • Entrecomilla los valores que podrían interpretarse mal como números, booleanos o fechas: version: "1.0".
  • Detecta errores rápido pegando el contenido en el validador YAML a JSON de FormatArc: los mensajes con número de línea apuntan directo al problema.

Qué es YAML y dónde lo verás

YAML (YAML Ain't Markup Language) es un formato de texto legible para datos estructurados. Cubre el mismo modelo de datos que JSON (cadenas, números, booleanos, nulos, listas y mapeos), pero su sintaxis se basa en la indentación en lugar de llaves y corchetes.

Si trabajas con herramientas modernas de DevOps o nativas de la nube, ya te has cruzado con YAML:

  • Manifiestos de Kubernetes y charts de Helm
  • Archivos de Docker Compose
  • Flujos de trabajo de GitHub Actions, GitLab CI y CircleCI
  • Playbooks de Ansible
  • Especificaciones OpenAPI
  • Generadores de sitios estáticos (Hugo, Jekyll, Eleventy)

Esta guía recorre cada parte de la sintaxis de YAML que realmente vas a usar, con ejemplos y una lista de los errores que más atrapan a los principiantes. Si quieres comparar YAML con JSON directamente, consulta YAML vs JSON: diferencias clave, o lee la guía paso a paso de cómo convertir YAML a JSON.

Los tres bloques de construcción

Todo en un archivo YAML es una de estas tres cosas:

  • Escalar: un único valor como una cadena, un número, un booleano o un nulo
  • Secuencia: una lista ordenada de elementos
  • Mapeo: un conjunto desordenado de pares clave-valor

Puedes anidarlos libremente. Un mapeo puede contener listas, una lista puede contener mapeos, y ambos pueden contener otros mapeos o listas. Eso es todo lo que necesitas para representar cualquier estructura compatible con JSON.

Reglas de indentación

La indentación es la forma en que YAML expresa el anidamiento. Algunas reglas que conviene interiorizar:

  • Usa espacios, nunca tabuladores: un carácter de tabulación literal es un error de sintaxis en la mayoría de los parsers
  • Elige un tamaño de indentación (2 espacios es la convención) y mantente coherente
  • Todos los elementos del mismo nivel deben tener la misma indentación
  • La indentación determina la estructura; no hay delimitador de cierre

Aquí tienes un ejemplo válido sencillo:

database:
  host: localhost
  port: 5432
  credentials:
    user: admin
    password: secret

database contiene un mapeo, que a su vez contiene host, port y credentials. credentials es un mapeo anidado. La indentación de dos espacios le indica a YAML exactamente cómo encaja la estructura.

Escribir pares clave-valor (mapeos)

Un mapeo se escribe como key: value, con un espacio después de los dos puntos. El espacio es obligatorio: key:value es una sola cadena, no un mapeo.

name: Alice
age: 30
is_admin: true
bio: null

Las claves suelen ser cadenas simples. Pueden contener espacios si se entrecomillan:

"full name": Alice Cooper

Los valores pueden ser cualquier tipo de YAML: escalar, secuencia u otro mapeo.

Escribir listas (secuencias)

Una secuencia es una serie de líneas que comienzan con - (un guion seguido de un espacio).

fruits:
  - apple
  - banana
  - cherry

Las listas pueden contener cualquier tipo de valor, incluidos mapeos anidados:

users:
  - name: Alice
    role: admin
  - name: Bob
    role: editor

Cada guion inicia un nuevo elemento de la lista. Los campos que le siguen pertenecen a ese elemento hasta que aparece otro guion al mismo nivel de indentación.

Estilo de bloque y estilo de flujo

Todo lo anterior es estilo de bloque: un elemento por línea, la indentación marca el anidamiento. YAML también tiene una forma en línea (de flujo) que se parece a JSON:

fruits: [apple, banana, cherry]
users: [{name: Alice, role: admin}, {name: Bob, role: editor}]

La forma de flujo resulta práctica para listas pequeñas, pero se vuelve más difícil de leer a medida que crecen los datos. Quédate con la forma de bloque para cualquier cosa que no sea trivial. Si dejas una colección de flujo sin cerrar, cada parser lo reporta de forma distinta: consulta la fila "Flujo [ sin cerrar" en la tabla de mensajes por parser más abajo.

Cadenas: cuándo entrecomillar

La mayoría de las cadenas en YAML se pueden escribir sin comillas.

greeting: Hello, world

Solo necesitas comillas cuando:

  • El valor se interpretaría de otro modo como un tipo diferente: version: "1.0", country: "NO", postal_code: "07030"
  • El valor empieza con un carácter que YAML lee como estructura: [, ], {, }, ,, *, |, >, %, @, `, ", ', o #, &, !. Un -, : o ? inicial solo da problemas cuando lo sigue un espacio
  • El valor contiene dos puntos seguidos de un espacio (lo que de otro modo parecería un mapeo)
  • Quieres incluir secuencias de escape como \n o \t

YAML admite comillas simples y dobles. Las comillas dobles interpretan las secuencias de escape; las comillas simples tratan todo de forma literal.

escaped: "line1\nline2"
literal: 'line1\nline2'

Los caracteres que de verdad causan problemas se dividen en dos grupos, y el grupo decide si hacen falta comillas. La tabla siguiente es lo que hace el parser de nuestro propio conversor (yaml (eemeli) 2.8.3, YAML.parse con los valores por defecto; medido el 2026-08-15, script de reproducción en el repositorio, en scripts/benchmarks/yaml-quote-requirements/). Léela así: cuando la columna central dice "seguro", puedes dejar el valor sin comillas siempre que el carácter no vaya al principio.

CarácterAl principio del valorEn medio del valorBasta con comillas simplesComillas dobles
[ ] { } ,Error de parseoSeguroTambién valen
*Error de parseo (se lee como alias)SeguroTambién valen
&Sin error: se convierte en ancla y el valor se pierdeSeguroTambién valen
!Sin error: se convierte en etiquetaSeguroTambién valen
#Sin error: el valor entero se lee como comentario y queda en nullSeguro salvo que lo preceda un espacioTambién valen
| >Error de parseo (se lee como escalar de bloque)SeguroTambién valen
% @ `Error de parseo (reservados)SeguroTambién valen
- ?Seguro por sí solos, error de parseo cuando los sigue un espacioSeguroTambién valen
:Seguro por sí solo, error de parseo cuando lo sigue un espacioError de parseo cuando lo sigue un espacio, esté donde estéTambién valen
"Error de parseoSeguroSolo con escapes \"
'Error de parseoSeguroNo: dóblala como ''Usa estas

De aquí salen dos cosas. Primero, en medio del valor solo son peligrosos : y #, así que url: http://example.com/a,b no necesita comillas: todo lo demás es un problema de principio de valor. Segundo, las comillas simples cubren todos los casos salvo una comilla simple literal, y por eso son la opción más segura cuando pegas rutas de Windows o expresiones regulares. Recurre a las comillas dobles cuando necesites que \n o \t signifiquen un salto de línea o un tabulador de verdad.

La sintaxis de plantillas {{ }} al inicio de un valor rompe el YAML

Si pasas una plantilla de Helm o un archivo de Ansible sin renderizar directamente a un parser de YAML, la llave inicial { activa la trampa de los caracteres especiales:

# Plantilla de Helm, antes de renderizar
image: {{ .Values.image }}

El {{ se parsea como dos mapeos de flujo anidados, y el modo de fallo depende del parser. En nuestras pruebas (2026-07-12, script de reproducción en el repositorio bajo scripts/benchmarks/yaml-syntax-errors/), PyYAML y ruamel.yaml se detienen con un error found unhashable key, pero js-yaml y eemeli/yaml no lanzan ningún error y devuelven en silencio un objeto deformado como {"image": {"[object Object]": null}}. La versión silenciosa es la peligrosa, porque nada falla hasta mucho después en tu pipeline.

Hay dos soluciones: entrecomillar el valor completo para que sea una cadena (image: "{{ .Values.image }}"), o validar el YAML solo después de renderizar la plantilla. Ten en cuenta que el ${{ }} de GitHub Actions empieza por $, así que nunca se parsea como un mapeo de flujo y no tiene este problema.

Cadenas multilínea

YAML tiene dos operadores para bloques de texto largos.

El bloque literal (|) conserva los saltos de línea exactamente como están escritos:

description: |
  This is line one.
  This is line two.

  This is line four, after a blank line.

El escalar plegado (>) reemplaza los saltos de línea simples por espacios, lo que resulta útil para ajustar párrafos largos en el archivo fuente:

paragraph: >
  This long sentence is split across
  multiple lines in the source, but YAML
  will fold it into a single line.

Indicadores de recorte: eliminar, recortar y conservar los saltos de línea finales

Los escalares de bloque de YAML aceptan un indicador de recorte (chomping) que decide qué ocurre con los saltos de línea finales después del valor. El indicador va inmediatamente después de | o >.

IndicadorComportamientoEjemplo
(ninguno) — clipConserva un único salto de línea final. Predeterminado.|
- — stripElimina todos los saltos de línea finales.|- >-
+ — keepConserva todas las líneas en blanco finales.|+ >+
clip: |
  line one
  line two
strip: |-
  line one
  line two
keep: |+
  line one
  line two

Los mismos tres modos se aplican a la forma plegada (>, >-, >+). Usa |- cuando incrustes YAML dentro de un JSON o de una variable de entorno que no debe tener un salto de línea final. Usa |+ cuando generes scripts en los que las líneas en blanco finales importan.

Tipos e inferencia del parser

YAML infiere los tipos a partir de los valores sin comillas. El mismo literal puede convertirse en un entero, un número de coma flotante, una fecha o una cadena según la versión de YAML que implemente tu parser y el esquema que utilice.

integer: 42
hex: 0xFF              # 255 (integer, hexadecimal)
octal: 0o17            # 15 (integer, octal, YAML 1.2)
octal_legacy: 0644     # 420 (integer, octal, YAML 1.1) — trampa del modo de archivo
float: 3.14
negative: -7
exponential: 1e3       # 1000.0 (float, notación científica)
infinity: .inf         # +Infinity (float)
negative_infinity: -.inf
not_a_number: .nan     # NaN (float)
boolean_true: true
boolean_false: false
null_value: null
tilde_null: ~
date: 2026-04-13
timestamp: 2026-04-13T09:30:00Z

Cualquiera de estos puede forzarse a cadena entrecomillándolo:

version_string: "1.0"    # no es el número 1.0
zip_code: "07030"        # no es el número 7030
file_mode: "0644"        # string, no un entero octal

La siguiente tabla resume en qué se convierten los literales sin comillas en un cargador moderno con esquema Core de YAML 1.2 (PyYAML, js-yaml, el predeterminado de SnakeYAML), frente a un cargador de YAML 1.1 (PyYAML antiguo, Symfony YAML). La mayoría de las sorpresas viven en la diferencia entre estas columnas.

LiteralYAML 1.2 CoreYAML 1.1A qué prestar atención
42integer (42)integer (42)
0xFFinteger (255)integer (255)el parseo hexadecimal es intencional
0o17integer (15)(no reconocido)solo en YAML 1.2
0644integer (644)integer (420, octal)los modos de archivo cambian entre versiones
1e3float (1000.0)float (1000.0)algunas herramientas omiten .0 al mostrarlo
.inf / -.inffloat (±Infinity)float (±Infinity)no serializable en JSON
.nanfloat (NaN)float (NaN)no serializable en JSON
2026-04-13stringdate (objeto de fecha)el ida y vuelta JSON ↔ YAML cambia el tipo
2026-04-13T09:30Zstringtimestampel mismo problema
true / falsebooleanboolean
yes / no / on / offstringbooleanel "problema de Noruega"
NOstringboolean (false)se trata a continuación
~ / null / Null / NULLnullnullse parsean todas las grafías
1.0float (1.0)float (1.0)algunas herramientas lo reserializan como 1

Si tu parser está cerca de producción de algún modo, trata todo lo que aparezca en la columna de la derecha como un posible bug. La forma más rápida de averiguar qué versión usa tu cargador es pegar un archivo representativo en el conversor YAML a JSON de FormatArc e inspeccionar la salida JSON: "NO" frente a false, "2026-04-13" frente a una cadena de fecha ISO, y así sucesivamente.

La razón por la que existe esta diferencia entre columnas es que YAML 1.1 y YAML 1.2 definen la inferencia de tipos de forma distinta. YAML 1.1 arrastraba un amplio conjunto de etiquetas de tipo implícitas, incluidos los timestamps, los números sexagesimales (base 60) y el extenso vocabulario booleano que provoca el problema de Noruega. YAML 1.2 lo reemplazó por el esquema CoreSe abre en una pestaña nueva, más acotado, que limita los booleanos a true y false (la expresión regular del Core de la especificación también acepta las formas con mayúscula inicial y todo en mayúsculas True/TRUE/False/FALSE, pero ya no yes/no/on/off), elimina las etiquetas implícitas de timestamp y sexagesimal, y por lo demás refleja los tipos de valor de JSON. El conjunto completo de expresiones regulares que decide si un literal es un entero, un float, un booleano o un nulo está publicado en la especificación de YAML 1.2.2Se abre en una pestaña nueva. Cuando dos herramientas no se ponen de acuerdo sobre lo que significa un valor sin comillas, la diferencia casi siempre se remonta a que una implementa las reglas de tipos de la 1.1 y la otra implementa el esquema Core de la 1.2.

El problema de Noruega: cuando NO se convierte en false

El "problema de Noruega" es la trampa de YAML más citada. Los parsers de YAML 1.1 (que siguen siendo el predeterminado en muchas herramientas, incluidas PyYAML, Symfony YAML y las versiones antiguas de SnakeYAML) interpretan un NO simple como el booleano false. Así que una lista de códigos de país escrita de esta manera:

countries:
  - DE
  - FR
  - NO
  - SE

se convierte silenciosamente en ["DE", "FR", false, "SE"] al parsearse. La misma trampa salta con YES, ON, OFF, Y, N e incluso con variantes en mayúsculas según el parser.

La solución es entrecomillar cualquier valor que pueda interpretarse mal:

countries:
  - "DE"
  - "FR"
  - "NO"
  - "SE"

YAML 1.2 redujo los booleanos solo a true y false, pero la mayoría de las herramientas de producción todavía incluyen un cargador de la era 1.1. Cuando escribas códigos de país, códigos de idioma de dos letras, cadenas de versión o cualquier identificador corto, entrecomíllalo. Si mantienes una configuración independiente del parser, pégala en el conversor YAML a JSON de FormatArc: la salida JSON muestra al instante si tu NO sobrevivió como cadena.

Las reglas exactas viven en las especificaciones oficiales: la especificación de YAML 1.2.2Se abre en una pestaña nueva define el conjunto estricto de booleanos actual, mientras que la especificación de YAML 1.1Se abre en una pestaña nueva es la que todavía implementan la mayoría de las herramientas heredadas. Saber qué versión sigue tu cargador te dice si NO se parsea como cadena o como false.

Comentarios

Los comentarios comienzan con # y se extienden hasta el final de la línea. Pueden ocupar una línea propia o ir después de un valor.

# Número máximo de reintentos para las peticiones al upstream
retries: 3  # Más que esto y superamos el tiempo de espera del upstream

Los comentarios son una de las mayores ventajas de YAML sobre JSON para archivos de configuración: úsalos para explicar por qué existe un ajuste, no qué es. Al convertir a JSON se eliminan todos los comentarios, así que mantén el archivo YAML como tu fuente de la verdad. Si tienes que apañártelas con JSON, consulta cómo añadir comentarios a JSON para conocer las soluciones con JSONC y JSON5.

Anclas y alias para reutilizar

YAML te permite definir un valor una vez con &anchor y referenciarlo en otro lugar con *alias. La clave de fusión <<: incorpora un mapeo como un conjunto de valores predeterminados.

defaults: &defaults
  adapter: postgres
  host: db.internal
  pool: 5

development:
  <<: *defaults
  database: myapp_dev

production:
  <<: *defaults
  database: myapp_prod
  pool: 20

production parte de defaults y luego sobrescribe pool. Es una forma limpia de compartir configuración entre entornos sin copiar y pegar.

Claves de fusión (<<:) para compartir configuración

La clave de fusión <<: es el complemento más útil de las anclas. Incorpora las claves de un mapeo en otro, de modo que puedes expresar "igual que aquel, pero con estos cambios" sin repetirte. Docker Compose, GitLab CI y el database.yml de Rails dependen de este patrón.

base: &base
  image: node:20
  restart: unless-stopped
  environment:
    NODE_ENV: production

services:
  api:
    <<: *base
    command: npm run start:api
  worker:
    <<: *base
    command: npm run start:worker
    environment:
      NODE_ENV: production
      WORKER_QUEUE: high

Dos cosas que recordar:

  • La clave de fusión solo fusiona en un nivel. Los mapeos anidados (como environment arriba) se reemplazan por completo, no se fusionan en profundidad.
  • La clave de fusión es una característica de YAML 1.1. Los parsers estrictos de YAML 1.2 pueden ignorarla; herramientas como Docker Compose y GitLab la siguen admitiendo porque se anclan a la semántica de 1.1.

Esquemas y etiquetas: cómo decide YAML los tipos

YAML 1.2 define tres esquemas que controlan cómo se interpretan los literales sin comillas:

  • FailSafe: solo cadenas, mapeos y secuencias. El esquema más seguro; todo lo demás es una cadena. Rara vez es el predeterminado.
  • JSON: tipos compatibles con JSON: cadena, entero, coma flotante, booleano, nulo, mapeo y secuencia. Coincide con lo que produciría JSON.parse.
  • Core: el predeterminado habitual. Añade las reglas de inferencia de tipos de la tabla anterior (hex, octal, .inf, .nan, ~).

La mayoría de los parsers incluyen Core (safe_load de PyYAML, el predeterminado de js-yaml, SafeConstructor de SnakeYAML). Symfony YAML sigue usando por defecto la semántica de YAML 1.1. Saber qué esquema usa tu cargador te dice qué fila de la tabla de tipos aplica.

Cuando el esquema se equivoca (por ejemplo, version: 1.0 se parsea como coma flotante cuando querías una cadena), usa una etiqueta explícita para anularlo:

version: !!str 1.0       # fuerza la cadena "1.0"
count: !!int "42"        # fuerza el entero 42 aunque esté entre comillas
empty: !!null ""         # null explícito en lugar de cadena vacía

El prefijo !! significa "usa la etiqueta de la biblioteca de etiquetas predeterminada". Las etiquetas personalizadas usan un solo ! (por ejemplo, !Ref en las plantillas de CloudFormation) y requieren que el parser las entienda. La mayoría de los archivos YAML a nivel de aplicación solo necesitan !!str para desactivar las trampas de tipos.

Archivos con múltiples documentos

Un único archivo YAML puede contener varios documentos separados por ---.

---
kind: Service
name: web
---
kind: Deployment
name: web
replicas: 3

Este es el mismo formato que usa Kubernetes cuando concatenas varios manifiestos. JSON no tiene equivalente: convertir un YAML de múltiples documentos a JSON te obliga a elegir un solo documento o a envolverlos en un array externo.

Dónde funcionan realmente las anclas, las claves de fusión y los múltiples documentos (matriz de compatibilidad)

Las anclas, las claves de fusión y los flujos de múltiples documentos son todos YAML válido, pero que funcionen depende por completo de dónde los pegues. Medimos directamente los cuatro parsers y Docker Compose (2026-07-12, scripts de reproducción en el repositorio bajo scripts/benchmarks/yaml-tool-acceptance/) y consultamos las fuentes oficiales de las plataformas alojadas.

EntornoAnclas & *Claves de fusión <<:Múltiples documentos ---
js-yamlCompatible (medido)Compatible (medido)load da error; usa loadAll (medido)
PyYAMLCompatible (medido)Compatible (medido)safe_load da error; usa safe_load_all (medido)
yaml (eemeli), el parser detrás del conversor de FormatArcCompatible (medido)No se expande por defecto: << queda como clave literal (medido)parse da error; usa parseAllDocuments (medido)
Docker Compose v5.3.0Compatible (medido)Compatible (medido)Aceptado: los documentos se fusionan en una sola configuración (medido)
GitHub ActionsCompatible desde el 2025-09-18Se abre en una pestaña nuevaNo compatible: falla con un error de sintaxisSe abre en una pestaña nuevaNo se menciona en la documentación oficial
GitLab CICompatibleSe abre en una pestaña nuevaCompatibleSe abre en una pestaña nuevaNo se menciona en la documentación oficial
Kubernetes (kubectl)No explícito en la documentación oficialNo explícito en la documentación oficialCompatibleSe abre en una pestaña nueva

Tres cosas que conviene notar:

  • GitHub Actions separa el par: las anclas llegaron en septiembre de 2025, pero <<: sigue fallando con un error de sintaxis, así que un workflow copiado desde GitLab CI no se traslada limpiamente.
  • eemeli/yaml usa YAML 1.2 por defecto, versión que eliminó las claves de fusión de la especificación, así que <<: no se expande y acabas en silencio con una clave literal "<<" en lugar de los valores fusionados.
  • La compatibilidad con múltiples documentos es una cuestión de API: los cuatro parsers rechazan los flujos --- a través de su API de documento único y los aceptan a través de la de múltiples documentos.

Ejemplos de YAML del mundo real

Las mismas reglas de sintaxis aplican tanto si escribes una configuración de cinco líneas como un manifiesto de producción. Aquí están los tres lugares más comunes donde te encontrarás con YAML en 2026.

Manifiesto de Deployment de Kubernetes

Un Deployment mínimo ejercita mapeos, secuencias, cadenas multilínea y los booleanos del problema de Noruega, todo a la vez. La mayoría de los fallos aquí provienen de desviaciones de indentación en el bloque spec.template.spec.containers.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.27-alpine
          ports:
            - containerPort: 80
          env:
            - name: FEATURE_FLAG_NEW_HEADER
              value: "true"      # entrecomillado a propósito: true sin comillas es un booleano
          resources:
            limits:
              cpu: "500m"
              memory: 256Mi

Fíjate en que value: "true" está entrecomillado. Sin las comillas, Kubernetes aceptaría tranquilamente el booleano y tu contenedor recibiría True (al estilo de Python) o no arrancaría, según el lenguaje. El desglose error por error está en la siguiente sección.

Flujo de trabajo de GitHub Actions

Los flujos de trabajo de GitHub Actions son mapeos profundamente anidados con frecuentes scripts multilínea. El bloque run es donde los modificadores | (literal) y > (plegado) de YAML demuestran su valor.

name: CI
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "20"      # entrecomillado para conservar el cero final
      - name: Install
        run: npm ci
      - name: Test
        run: |
          npm run lint
          npm run build
          npm test -- --run

El fallo más común aquí es quitar las comillas de node-version: "20": YAML lo convierte en el entero 20, que setup-node puede aceptar o no según la versión. Entrecomilla cualquier valor que "parezca" un número pero que deba seguir siendo una cadena.

Servicio de Docker Compose

Los archivos de Compose mezclan mapeos, secuencias, diccionarios de entorno y cadenas de montaje (bind-mount). Son lo bastante cortos como para pegarse completos y son una excelente forma de practicar la detección de problemas de indentación.

services:
  web:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"               # entrecomillado para evitar la lectura sexagesimal
    environment:
      NGINX_HOST: example.com
      NGINX_PORT: "80"          # entrecomillado: los valores de entorno deben ser cadenas
    volumes:
      - ./html:/usr/share/nginx/html:ro
    depends_on:
      - api
  api:
    build: ./api
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 5s
      retries: 3

Dos trampas sutiles aquí: "8080:80" debe entrecomillarse (de lo contrario, los parsers de YAML 1.1 pueden leerlo como un número sexagesimal), y todos los valores bajo environment: deberían entrecomillarse porque Docker Compose finalmente necesita cadenas. Los errores que vienen a continuación muestran qué aspecto tienen cuando salen mal.

Errores comunes, y qué dice exactamente cada parser sobre ellos (medido)

Estos son los errores de YAML que en algún momento atrapan a casi todo el mundo.

  • Tabuladores en lugar de espacios: un carácter de tabulación oculto rompe el parseo con un error confuso
  • Falta de espacio después de los dos puntos: key:value es una sola cadena, no un mapeo
  • Indentación inconsistente: los elementos del mismo nivel deben compartir la misma indentación
  • Booleanos a partir de NO, OFF, YES, ON sin comillas: el "problema de Noruega"
  • Dos puntos en valores sin comillas: time: 10:30 podría parsearse como un número sexagesimal
  • Mezclar la sintaxis de bloque y de flujo de formas que el parser no espera
  • Claves duplicadas en el mismo mapeo: el comportamiento depende de la implementación

Lo molesto cuando buscas estos errores es que el mismo fallo produce un mensaje completamente distinto en cada parser. Pasamos seis errores representativos a js-yaml, a yaml (eemeli) —el parser detrás del conversor de FormatArc— y a PyYAML, y registramos las cadenas exactas que emiten (medido el 2026-07-12; los registros en bruto de los cuatro parsers, incluido ruamel.yaml, junto con el script de reproducción, están en el repositorio bajo scripts/benchmarks/yaml-syntax-errors/). El script de reproducción cubre también un séptimo caso, la trampa de las plantillas {{ }}, pero ese tiene su propia sección más arriba, así que no se repite en esta tabla.

ErrorMensaje de js-yamlMensaje de yaml (eemeli)Mensaje de PyYAML
Tabulador usado para indentartab characters must not be used in indentation (línea 2)Tabs are not allowed as indentation (línea 2)found character '\t' that cannot start any token (línea 2)
Indentación inconsistente (2 vs 3 espacios)bad indentation of a mapping entry (línea 3)Nested mappings are not allowed in compact mappings (línea 2)mapping values are not allowed here (línea 3)
: sin comillas dentro de un valor (url: http://x.com: 8080)bad indentation of a mapping entry (línea 1, col 24)Nested mappings are not allowed in compact mappings (línea 1, col. 6)mapping values are not allowed here (línea 1, col 24)
Comilla doble sin cerrarunexpected end of the stream within a double quoted scalar (última línea)Missing closing "quote (línea 2, col. 8)while scanning a quoted scalar ... found unexpected end of stream (apunta a la comilla de apertura)
*alias a un ancla no definidaunidentified alias "missing"Unresolved alias (the anchor must be set before the alias): missing (no informa la línea)found undefined alias 'missing'
Flujo [ sin cerrarmissed comma between flow collection entries (línea siguiente)Flow sequence in block collection must be sufficiently indented and end with a ] (línea 2)while parsing a flow sequence ... expected ',' or ']'

Tres consejos para leerlos. Primero, mapping values are not allowed here (PyYAML) y bad indentation of a mapping entry (js-yaml) parecen no tener relación, pero son errores hermanos: ambos significan "hay un : donde no puede empezar un mapeo", y el Nested mappings are not allowed in compact mappings de eemeli es el mismo diagnóstico con una tercera redacción. Segundo, el número de línea reportado cambia entre parsers: ante una comilla sin cerrar, js-yaml apunta al final del flujo mientras que PyYAML apunta a la comilla de apertura, así que revisa tanto la línea reportada como el punto donde abre la comilla más cercana. Tercero, ante el mismo documento eemeli suele apuntar una línea antes que js-yaml, porque informa dónde empezó el mapeo compacto y no dónde se rompió.

La forma más rápida de detectarlos es dejar que un parser lea el archivo. Puedes hacerlo sin instalar nada pegando tu YAML en el conversor YAML a JSON de FormatArc. Si el archivo es válido, verás el equivalente en JSON al instante. Si no lo es, el conversor te dice que el documento tiene un error de sintaxis y te da la línea a la que saltar: a propósito no imprime el mensaje en bruto del parser, así que, cuando quieras buscar la redacción exacta que emite tu propia cadena de herramientas, usa la tabla anterior.

Solución: "It is forbidden to specify block composed value at the same line as key"

Se trata de una inspección de YAML de la familia de IDEs JetBrains/IntelliJ (IntelliJ IDEA, PyCharm, GoLand, Rider, DataGrip). El texto exacto está definido en YAMLBundle.propertiesSe abre en una pestaña nueva como annotator.same.line.composed.value.message.

El mensaje significa una sola cosa: una colección de bloque empieza en la misma línea que su clave. Al leer el código del annotatorSe abre en una pestaña nueva se ve que solo comprueba dos formas: una secuencia de bloque cuyo primer elemento comparte línea con la clave, y un mapeo de bloque cuyo primer par clave-valor comparte línea con la clave. Nada más la dispara.

Forma 1: una secuencia de bloque que empieza en la línea de la clave.

# Dispara la inspección
key: - item1
     - item2

Solución: baja el primer elemento a su propia línea.

key:
  - item1
  - item2

Forma 2: un mapeo de bloque que empieza en la línea de la clave.

# Dispara la inspección
key: sub: value
     sub2: value2

Solución: el mismo tratamiento, cortar después de los dos puntos.

key:
  sub: value
  sub2: value2

Ninguna de las dos formas es una manía del IDE: son errores de YAML. Los parsers también las rechazan, con un texto cercano al de IntelliJ. El paquete yaml devuelve Unexpected block-seq-ind on same line with key para la forma 1 y Nested mappings are not allowed in compact mappings para la forma 2.

No es la inspección de claves duplicadas. Las claves de mapeo duplicadas producen otro mensaje, Key 'x' is duplicated (YAMLDuplicatedKeysInspection.duplicated.key en el mismo bundle). Si tu IDE dice que una clave está duplicada, la solución es renombrarla o cambiarla de padre, y no tiene relación con dónde empieza la colección de bloque.

Cuando el mensaje aparece en plantillas Helm o Jinja válidas. El annotator interrumpe la comprobación cuando el elemento contiene fragmentos de plantilla inyectados, así que una plantilla bien escrita no debería marcarse. Si aun así aparece, es un falso positivo conocido — JetBrains lo registra en incidencias como IJPL-64437Se abre en una pestaña nueva — y el archivo no necesita ningún cambio.

Después de editar, pega el archivo en YAML a JSON para confirmar que la colección de bloque ya empieza en su propia línea. La conversión se ejecuta por completo en tu navegador: tu YAML no se sube a ningún sitio.

Valida tu YAML en el navegador con FormatArc

Las herramientas exclusivamente de navegador de FormatArc funcionan muy bien como un linter rápido de YAML:

Resultado de la conversión de YAML a JSON mostrando un parseo correcto con diagnósticos por número de líneaResultado de la conversión de YAML a JSON mostrando un parseo correcto con diagnósticos por número de línea

  • YAML a JSON: pega YAML, ve la salida JSON y obtén errores con número de línea cuando algo está mal
  • JSON a YAML: ¿partes de JSON y quieres ver el equivalente en YAML? Úsalo para aprender la correspondencia entre ambos formatos
  • Formateador de JSON: formatea con sangría el JSON que sale de tu YAML

Todo se ejecuta en el navegador. Nada sale de tu máquina, así que puedes pegar con seguridad archivos de configuración internos o secretos mientras depuras.

Preguntas frecuentes

¿Puedo usar tabuladores para la indentación en YAML?

No. La especificación de YAML exige espacios, y un carácter de tabulación literal producirá un error de sintaxis en la mayoría de los parsers. Configura tu editor para que inserte dos espacios al pulsar Tab en un archivo .yml o .yaml.

¿Cuál es la diferencia entre .yml y .yaml?

Ninguna. Todos los parsers de YAML tratan ambas extensiones de forma idéntica. La especificación oficial recomienda .yaml, pero .yml es común y está totalmente admitida.

¿Siempre necesito comillas alrededor de las cadenas?

No. YAML te permite escribir la mayoría de las cadenas sin comillas. Añade comillas solo cuando el valor se interpretaría de otro modo como un tipo diferente, o cuando comienza con un carácter especial como -, :, [, {, | o >.

¿Por qué version: 1.0 se convierte en 1?

YAML parsea 1.0 como un número de coma flotante, y algunas herramientas luego serializan el flotante como 1. Para mantenerlo como cadena, entrecomíllalo: version: "1.0".

¿Cuántos espacios debo usar para la indentación?

Dos es la convención que usan Kubernetes, Docker Compose, GitHub Actions y la mayoría de los ejemplos que verás en línea. Cuatro está bien siempre que seas coherente dentro de un mismo archivo.

¿Cómo valido un archivo YAML sin instalar nada?

Pégalo en el conversor YAML a JSON de FormatArc. Si el YAML es válido, verás la salida JSON al instante. Si no lo es, el mensaje de error incluye el número de línea para que puedas corregir el problema rápido.

¿Puedo escribir varios documentos YAML en un solo archivo?

Sí. Sepáralos con una línea que contenga únicamente ---. Así es como suelen empaquetarse los manifiestos de Kubernetes. Un único archivo YAML puede contener tantos documentos como quieras.

Lecturas relacionadas

Resumen

  • YAML usa la indentación, no llaves, para expresar la estructura
  • Solo espacios: nunca tabuladores, y sé coherente
  • Entrecomilla las cadenas solo cuando se malinterpretarían
  • Usa comentarios, cadenas multilínea y anclas para hacer legibles los archivos de configuración
  • Valida tu YAML rápido pegándolo en la herramienta YAML a JSON de FormatArc