Validador de sintaxe YAML do FormatArc mostrando erros com número de linha no navegadorValidador de sintaxe YAML do FormatArc mostrando erros com número de linha no navegador
Autor: Equipe editorial da FormatArcPublicado: 2026-04-13Atualizado: 2026-09-05

Como corrigir "Forbidden Block Composed Value" em YAML

TL;DR — sintaxe YAML em um minuto

  • Use apenas espaços (sem tabs). A indentação de 2 espaços é a convenção de fato.
  • key: value precisa de um espaço após os dois-pontos. key:value é uma única string.
  • Listas usam - (traço + espaço). Mapeamentos usam key: value.
  • Coloque entre aspas valores que poderiam ser mal interpretados como números, booleanos ou datas: version: "1.0".
  • Encontre erros rapidamente colando no validador de YAML para JSON do FormatArc — as mensagens com número de linha apontam direto para o problema.

O que é YAML e onde você vai encontrá-lo

YAML (YAML Ain't Markup Language) é um formato de texto legível para humanos voltado a dados estruturados. Ele cobre o mesmo modelo de dados do JSON — strings, números, booleanos, nulos, listas e mapeamentos — mas a sintaxe é baseada em indentação, e não em chaves e colchetes.

Se você trabalha com ferramentas modernas de DevOps ou cloud-native, já se deparou com YAML:

  • Manifestos do Kubernetes e Helm charts
  • Arquivos do Docker Compose
  • Workflows de GitHub Actions, GitLab CI e CircleCI
  • Playbooks do Ansible
  • Especificações OpenAPI
  • Geradores de sites estáticos (Hugo, Jekyll, Eleventy)

Este guia percorre cada parte da sintaxe YAML que você de fato vai usar, com exemplos e uma lista dos erros que mais pegam os iniciantes. Se quiser comparar YAML e JSON diretamente, veja YAML vs JSON: principais diferenças, ou leia o passo a passo Como converter YAML para JSON.

Os três blocos de construção

Tudo em um arquivo YAML é uma de três coisas:

  • Escalar — um único valor, como uma string, número, booleano ou nulo
  • Sequência — uma lista ordenada de itens
  • Mapeamento — um conjunto não ordenado de pares chave-valor

Você pode aninhar esses elementos livremente. Um mapeamento pode conter listas, uma lista pode conter mapeamentos, e ambos podem conter outros mapeamentos ou listas. Isso é tudo de que você precisa para representar qualquer estrutura compatível com JSON.

Regras de indentação

A indentação é como o YAML expressa o aninhamento. Algumas regras para internalizar:

  • Use espaços, nunca tabs — um caractere de tab literal é um erro de sintaxe na maioria dos parsers
  • Escolha um tamanho de indentação (2 espaços é a convenção) e mantenha a consistência
  • Todos os itens no mesmo nível devem ter a mesma indentação
  • A indentação determina a estrutura; não existe delimitador de fechamento

Aqui está um exemplo simples e válido:

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

database contém um mapeamento, que contém host, port e credentials. credentials é um mapeamento aninhado. A indentação de dois espaços diz ao YAML exatamente como a estrutura se encaixa.

Escrevendo pares chave-valor (mapeamentos)

Um mapeamento é escrito como key: value, com um espaço após os dois-pontos. O espaço é obrigatório — key:value é uma única string, não um mapeamento.

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

As chaves normalmente são strings simples. Elas podem conter espaços se estiverem entre aspas:

"full name": Alice Cooper

Os valores podem ser de qualquer tipo YAML: escalar, sequência ou outro mapeamento.

Escrevendo listas (sequências)

Uma sequência é uma série de linhas que começam com - (um traço seguido de um espaço).

fruits:
  - apple
  - banana
  - cherry

As listas podem conter qualquer tipo de valor, incluindo mapeamentos aninhados:

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

Cada traço inicia um novo item da lista. Os campos que se seguem pertencem a esse item até que outro traço apareça no mesmo nível de indentação.

Estilo de bloco e estilo flow

Tudo o que vimos até aqui é estilo de bloco: um item por linha, a indentação mostra o aninhamento. O YAML também tem uma forma inline (flow) que se parece com JSON:

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

A forma flow é prática para listas pequenas, mas fica mais difícil de ler quando os dados crescem. Use a forma em bloco para qualquer coisa não trivial. Se você deixar uma coleção flow sem fechar, cada parser reporta isso de um jeito diferente: veja a linha "Flow [ não fechado" na tabela de mensagens por parser logo abaixo.

Strings: quando usar aspas

A maioria das strings em YAML pode ser escrita sem aspas.

greeting: Hello, world

Você só precisa de aspas quando:

  • O valor seria, de outra forma, interpretado como um tipo diferente: version: "1.0", country: "NO", postal_code: "07030"
  • O valor começa com um caractere que o YAML lê como estrutura: [, ], {, }, ,, *, |, >, %, @, `, ", ', ou #, &, !. Um -, : ou ? inicial só é problema quando vem um espaço logo depois
  • O valor contém dois-pontos seguidos de um espaço (que, de outra forma, pareceria um mapeamento)
  • Você quer incluir sequências de escape, como \n ou \t

O YAML aceita aspas simples e duplas. As aspas duplas interpretam as sequências de escape; as aspas simples tratam tudo literalmente.

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

Os caracteres que realmente causam problema se dividem em dois grupos, e o grupo decide se as aspas são necessárias. A tabela abaixo é o que o parser do nosso próprio conversor faz (yaml (eemeli) 2.8.3, YAML.parse com os padrões; medido em 2026-08-15, script de reprodução no repositório, em scripts/benchmarks/yaml-quote-requirements/). Leia assim: quando a coluna do meio diz "seguro", você pode deixar o valor sem aspas desde que o caractere não fique na frente.

CaractereNo início do valorNo meio do valorAspas simples bastamAspas duplas
[ ] { } ,Erro de parseSeguroSimTambém servem
*Erro de parse (lido como alias)SeguroSimTambém servem
&Sem erro: vira uma âncora e o valor se perdeSeguroSimTambém servem
!Sem erro: vira uma tagSeguroSimTambém servem
#Sem erro: o valor inteiro é lido como comentário e vira nullSeguro, a menos que venha um espaço antesSimTambém servem
| >Erro de parse (lido como escalar de bloco)SeguroSimTambém servem
% @ `Erro de parse (reservados)SeguroSimTambém servem
- ?Seguros sozinhos, erro de parse quando vem um espaço depoisSeguroSimTambém servem
:Seguro sozinho, erro de parse quando vem um espaço depoisErro de parse quando vem um espaço depois, em qualquer posiçãoSimTambém servem
"Erro de parseSeguroSimSó com escapes \"
'Erro de parseSeguroNão: duplique como ''Use estas

Duas coisas saem daí. Primeiro, no meio do valor só : e # são perigosos, então url: http://example.com/a,b não precisa de aspas nenhuma: todo o resto é problema de início de valor. Segundo, as aspas simples cobrem todos os casos, menos uma aspa simples literal, e é por isso que elas são o padrão mais seguro quando você cola caminhos do Windows ou expressões regulares. Recorra às aspas duplas quando precisar que \n ou \t signifiquem uma quebra de linha ou uma tabulação de verdade.

A sintaxe de template {{ }} no início de um valor quebra o YAML

Se você passar um template do Helm ou um arquivo do Ansible sem renderizar direto para um parser de YAML, a chave inicial { dispara a armadilha dos caracteres especiais:

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

O {{ é parseado como dois mapeamentos de flow aninhados — e o modo de falha depende do parser. Nos nossos testes (2026-07-12, script de reprodução no repositório em scripts/benchmarks/yaml-syntax-errors/), o PyYAML e o ruamel.yaml param com um erro found unhashable key, mas o js-yaml e o eemeli/yaml não levantam erro nenhum e retornam silenciosamente um objeto deformado como {"image": {"[object Object]": null}}. A versão silenciosa é a perigosa, porque nada falha até bem mais adiante no seu pipeline.

Há duas soluções: colocar o valor inteiro entre aspas para que ele vire uma string (image: "{{ .Values.image }}"), ou validar o YAML apenas depois que o template tiver sido renderizado. Note que o ${{ }} do GitHub Actions começa com $, então ele nunca é parseado como um mapeamento de flow e não tem esse problema.

Strings de várias linhas

O YAML tem dois operadores para blocos de texto longos.

O bloco literal (|) preserva as quebras de linha exatamente como foram escritas:

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

  This is line four, after a blank line.

O escalar dobrado (>) substitui quebras de linha simples por espaços, o que é útil para quebrar parágrafos longos no arquivo de origem:

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

Indicadores de chomp: strip, clip e manter quebras de linha finais

Os escalares em bloco do YAML aceitam um indicador de chomping que decide o que acontece com as quebras de linha finais após o valor. O indicador vem imediatamente após | ou >.

IndicadorComportamentoExemplo
(nenhum) — clipMantém uma única quebra de linha final. Padrão.|
- — stripRemove todas as quebras de linha finais.|- >-
+ — keepMantém todas as linhas em branco finais.|+ >+
clip: |
  line one
  line two
strip: |-
  line one
  line two
keep: |+
  line one
  line two

Os mesmos três modos se aplicam à forma dobrada (>, >-, >+). Use |- quando você embute YAML dentro de um JSON ou de uma variável de ambiente que não pode ter uma quebra de linha final. Use |+ quando você gera scripts em que as linhas em branco finais importam.

Tipos e inferência do parser

O YAML infere tipos a partir de valores sem aspas. O mesmo literal pode se tornar um inteiro, um float, uma data ou uma string, dependendo da versão do YAML que o seu parser implementa e de qual schema ele usa.

integer: 42
hex: 0xFF              # 255 (integer, hexadecimal)
octal: 0o17            # 15 (integer, octal, YAML 1.2)
octal_legacy: 0644     # 420 (integer, octal, YAML 1.1) — armadilha do modo de arquivo
float: 3.14
negative: -7
exponential: 1e3       # 1000.0 (float, notação 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

Qualquer um desses pode ser forçado a virar string usando aspas:

version_string: "1.0"    # não é o número 1.0
zip_code: "07030"        # não é o número 7030
file_mode: "0644"        # string, não um inteiro octal

A próxima tabela resume no que os literais sem aspas se transformam em um loader moderno do schema Core do YAML 1.2 (PyYAML, js-yaml, o padrão do SnakeYAML), em comparação com um loader YAML 1.1 (PyYAML legado, Symfony YAML). A maioria das surpresas vive nessa diferença entre colunas.

LiteralYAML 1.2 CoreYAML 1.1Cuidado com
42integer (42)integer (42)
0xFFinteger (255)integer (255)o parse de hex é intencional
0o17integer (15)(não reconhecido)só no YAML 1.2
0644integer (644)integer (420, octal)modos de arquivo mudam entre versões
1e3float (1000.0)float (1000.0)a exibição perde o .0 em algumas ferramentas
.inf / -.inffloat (±Infinity)float (±Infinity)não serializável em JSON
.nanfloat (NaN)float (NaN)não serializável em JSON
2026-04-13stringdate (objeto de data)converter JSON ↔ YAML de ida e volta muda o tipo
2026-04-13T09:30Zstringtimestampmesmo problema
true / falsebooleanboolean
yes / no / on / offstringbooleano "problema da Noruega"
NOstringboolean (false)abordado a seguir
~ / null / Null / NULLnullnulltoda capitalização vira null
1.0float (1.0)float (1.0)re-serializado como 1 por algumas ferramentas

Se o seu parser está perto de produção, trate qualquer coisa na coluna mais à direita como um bug em potencial. A forma mais rápida de descobrir qual versão o seu loader usa é colar um arquivo representativo no conversor de YAML para JSON do FormatArc e inspecionar a saída JSON: "NO" versus false, "2026-04-13" versus uma string de data ISO, e assim por diante.

A razão de essa diferença entre colunas existir é que o YAML 1.1 e o YAML 1.2 definem a inferência de tipos de formas diferentes. O YAML 1.1 carregava um amplo conjunto de tags de tipo implícitas — incluindo timestamps, números sexagesimais (base 60) e o vasto vocabulário booleano que causa o problema da Noruega. O YAML 1.2 substituiu isso pelo schema CoreAbre em uma nova aba, mais restrito, que limita os booleanos a true e false (a regex do Core da especificação também aceita as formas com inicial maiúscula e tudo em maiúsculas True/TRUE/False/FALSE, mas não mais yes/no/on/off), descarta as tags implícitas de timestamp e sexagesimal e, no restante, espelha os tipos de valor do JSON. O conjunto completo de expressões regulares que decide se um literal é um inteiro, um float, um booleano ou um nulo está publicado na especificação do YAML 1.2.2Abre em uma nova aba. Quando duas ferramentas discordam sobre o que um valor sem aspas significa, a diferença quase sempre remonta a uma delas implementar as regras de tipo da 1.1 e a outra implementar o schema Core da 1.2.

O problema da Noruega: quando NO vira false

O "problema da Noruega" é a pegadinha de YAML mais citada. Os parsers do YAML 1.1 (ainda o padrão em muitas ferramentas — incluindo PyYAML, Symfony YAML e versões mais antigas do SnakeYAML) interpretam um NO sem aspas como o booleano false. Então uma lista de códigos de país escrita assim:

countries:
  - DE
  - FR
  - NO
  - SE

silenciosamente se torna ["DE", "FR", false, "SE"] depois de ser parseada. A mesma armadilha dispara para YES, ON, OFF, Y, N e até variantes em maiúsculas, dependendo do parser.

A correção é colocar entre aspas qualquer valor que possa ser mal interpretado:

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

O YAML 1.2 restringiu os booleanos a apenas true e false, mas a maioria das ferramentas de produção ainda traz um loader da era 1.1. Quando você escrever códigos de país, códigos de idioma de duas letras, strings de versão ou qualquer identificador curto, use aspas. Se você mantém uma config independente de parser, cole no conversor de YAML para JSON do FormatArc — a saída JSON mostra na hora se o seu NO sobreviveu como string.

As regras exatas estão nas especificações oficiais: a especificação do YAML 1.2.2Abre em uma nova aba define o conjunto estrito de booleanos de hoje, enquanto a especificação do YAML 1.1Abre em uma nova aba é a que a maioria das ferramentas legadas ainda implementa. Saber qual versão o seu loader segue diz se NO é parseado como string ou como false.

Comentários

Os comentários começam com # e vão até o fim da linha. Eles podem ocupar uma linha sozinhos ou vir depois de um valor.

# Número máximo de tentativas para as requisições ao upstream
retries: 3  # Acima disso, estouramos o timeout do upstream

Os comentários são uma das maiores vantagens do YAML sobre o JSON para arquivos de configuração — use-os para explicar por que uma configuração existe, não o que ela é. A conversão para JSON descarta todos os comentários, então mantenha o arquivo YAML como a sua fonte da verdade. Se você precisa conviver com JSON, veja Como adicionar comentários ao JSON para as soluções com JSONC e JSON5.

Âncoras e aliases para reutilização

O YAML permite que você defina um valor uma única vez com &anchor e o referencie em outro lugar com *alias. A chave de merge <<: traz um mapeamento como um conjunto de valores padrão.

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 e então sobrescreve pool. Essa é uma forma limpa de compartilhar configuração entre ambientes sem copiar e colar.

Chaves de merge (<<:) para compartilhar config

A chave de merge <<: é a companheira mais útil das âncoras. Ela traz as chaves de um mapeamento para dentro de outro, então você pode expressar "igual àquilo, mas com estas sobrescritas" sem se repetir. Docker Compose, GitLab CI e o database.yml do Rails dependem desse padrão.

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

Duas coisas para lembrar:

  • A chave de merge só faz merge em um nível. Mapeamentos aninhados (como environment acima) são substituídos por completo, e não combinados em profundidade.
  • A chave de merge é um recurso do YAML 1.1. Parsers estritos do YAML 1.2 podem ignorá-la; ferramentas como Docker Compose e GitLab ainda a suportam porque fixam a semântica da 1.1.

Schemas e tags: como o YAML decide os tipos

O YAML 1.2 define três schemas que controlam como os literais sem aspas são interpretados:

  • FailSafe — apenas strings, mapeamentos e sequências. O schema mais seguro; todo o resto é uma string. Raramente é o padrão.
  • JSON — tipos compatíveis com JSON: string, integer, float, boolean, null, mapeamento, sequência. Equivale ao que JSON.parse produziria.
  • Core — o padrão típico. Adiciona as regras de inferência de tipo da tabela acima (hex, octal, .inf, .nan, ~).

A maioria dos parsers traz o Core (safe_load do PyYAML, o padrão do js-yaml, o SafeConstructor do SnakeYAML). O Symfony YAML ainda usa por padrão a semântica do YAML 1.1. Saber qual schema o seu loader usa diz qual linha da tabela de tipos se aplica.

Quando o schema erra — version: 1.0 sendo parseado como float quando você queria uma string — use uma tag explícita para sobrescrever:

version: !!str 1.0       # força a string "1.0"
count: !!int "42"        # força o inteiro 42 mesmo entre aspas
empty: !!null ""         # null explícito em vez de string vazia

O prefixo !! significa "use a tag da biblioteca de tags padrão". Tags personalizadas usam um único ! (por exemplo !Ref em templates do CloudFormation) e exigem que o parser as entenda. A maioria dos arquivos YAML em nível de aplicação só precisa de !!str para desarmar as armadilhas de tipo.

Arquivos com vários documentos

Um único arquivo YAML pode conter vários documentos separados por ---.

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

Esse é o mesmo formato que o Kubernetes usa quando você concatena vários manifestos. O JSON não tem equivalente — converter um YAML com vários documentos para JSON obriga você a escolher um documento ou a envolvê-los em um array externo.

Onde âncoras, merge keys e múltiplos documentos realmente funcionam (matriz de compatibilidade)

Âncoras, merge keys e streams com múltiplos documentos são todos YAML válido — mas se eles funcionam depende inteiramente de onde você os cola. Medimos diretamente os quatro parsers e o Docker Compose (2026-07-12, scripts de reprodução no repositório em scripts/benchmarks/yaml-tool-acceptance/) e conferimos as fontes oficiais das plataformas hospedadas.

AmbienteÂncoras & *Merge keys <<:Múltiplos documentos ---
js-yamlSuportado (medido)Suportado (medido)load dá erro; use loadAll (medido)
PyYAMLSuportado (medido)Suportado (medido)safe_load dá erro; use safe_load_all (medido)
yaml (eemeli), o parser por trás do conversor do FormatArcSuportado (medido)Não é expandido por padrão — << permanece como chave literal (medido)parse dá erro; use parseAllDocuments (medido)
Docker Compose v5.3.0Suportado (medido)Suportado (medido)Aceito — os documentos são mesclados em uma única config (medido)
GitHub ActionsSuportado desde 2025-09-18Abre em uma nova abaNão suportado — falha com erro de sintaxeAbre em uma nova abaNão mencionado na documentação oficial
GitLab CISuportadoAbre em uma nova abaSuportadoAbre em uma nova abaNão mencionado na documentação oficial
Kubernetes (kubectl)Não explícito na documentação oficialNão explícito na documentação oficialSuportadoAbre em uma nova aba

Três pontos que valem a atenção:

  • O GitHub Actions separa o par: as âncoras chegaram em setembro de 2025, mas <<: ainda falha com erro de sintaxe — então um workflow copiado do GitLab CI não migra de forma limpa.
  • O eemeli/yaml usa YAML 1.2 por padrão, versão que removeu as merge keys da especificação, então <<: não é expandido — você acaba silenciosamente com uma chave literal "<<" em vez dos valores mesclados.
  • O suporte a múltiplos documentos é uma questão de API: os quatro parsers rejeitam streams --- pela API de documento único e os aceitam pela de múltiplos documentos.

Exemplos reais de YAML

As mesmas regras de sintaxe se aplicam, quer você esteja escrevendo uma config de cinco linhas ou um manifesto de produção. Aqui estão os três lugares mais comuns onde você vai encontrar YAML em 2026.

Manifesto de Deployment do Kubernetes

Um Deployment mínimo exercita mapeamentos, sequências, strings de várias linhas e os booleanos do problema da Noruega, tudo ao mesmo tempo. A maioria das falhas aqui vem de desvios de indentação no bloco 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"      # entre aspas de propósito: true sem aspas é um booleano
          resources:
            limits:
              cpu: "500m"
              memory: 256Mi

Repare que value: "true" está entre aspas. Sem as aspas, o Kubernetes aceitaria de bom grado o booleano e o seu container receberia True (estilo Python) ou falharia ao iniciar, dependendo da linguagem. A análise erro por erro está na próxima seção.

Workflow do GitHub Actions

Os workflows do GitHub Actions são mapeamentos profundamente aninhados com scripts de várias linhas frequentes. O bloco run é onde os modificadores | (literal) e > (dobrado) do YAML provam o seu 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"      # entre aspas para preservar o zero final
      - name: Install
        run: npm ci
      - name: Test
        run: |
          npm run lint
          npm run build
          npm test -- --run

A quebra mais comum aqui é remover as aspas em torno de node-version: "20" — o YAML o coage ao inteiro 20, que o setup-node pode ou não aceitar, dependendo da versão. Coloque entre aspas qualquer valor que "pareça" um número, mas que deva permanecer como string.

Serviço do Docker Compose

Os arquivos do Compose misturam mapeamentos, sequências, dicionários de ambiente e strings de bind-mount. Eles são curtos o suficiente para colar por inteiro e são uma ótima forma de praticar a identificação de problemas de indentação.

services:
  web:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"               # entre aspas para evitar a leitura sexagesimal
    environment:
      NGINX_HOST: example.com
      NGINX_PORT: "80"          # entre aspas: valores de ambiente precisam ser strings
    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

Duas armadilhas sutis aqui: "8080:80" precisa estar entre aspas (caso contrário, parsers do YAML 1.1 podem lê-lo como um número sexagesimal), e todo valor sob environment: deve estar entre aspas, porque o Docker Compose, no fim das contas, precisa de strings. Os erros a seguir mostram como isso fica quando dá errado.

Erros comuns — e o que cada parser realmente diz sobre eles (medido)

Estes são os erros de YAML que pegam quase todo mundo em algum momento.

  • Tabs em vez de espaços — um caractere de tab escondido quebra o parsing com um erro confuso
  • Falta de espaço após os dois-pontos — key:value é uma única string, não um mapeamento
  • Indentação inconsistente — itens no mesmo nível devem compartilhar a mesma indentação
  • Booleanos a partir de NO, OFF, YES, ON sem aspas — o "problema da Noruega"
  • Dois-pontos em valores sem aspas — time: 10:30 pode ser parseado como um número sexagesimal
  • Misturar sintaxe de bloco e de flow de formas que o parser não espera
  • Chaves duplicadas no mesmo mapeamento — o comportamento depende da implementação

O incômodo quando você pesquisa esses erros é que o mesmo engano produz uma mensagem completamente diferente em cada parser. Passamos seis erros representativos para o js-yaml, para o yaml (eemeli) — o parser por trás do conversor do FormatArc — e para o PyYAML, e registramos as strings exatas que eles emitem (medido em 2026-07-12; os logs brutos dos quatro parsers, incluindo o ruamel.yaml, junto com o script de reprodução, estão no repositório em scripts/benchmarks/yaml-syntax-errors/). O script de reprodução cobre também um sétimo caso, a armadilha dos templates {{ }}, mas ele tem uma seção própria acima, então não se repete nesta tabela.

ErroMensagem do js-yamlMensagem do yaml (eemeli)Mensagem do PyYAML
Tab usado para indentaçãotab characters must not be used in indentation (linha 2)Tabs are not allowed as indentation (linha 2)found character '\t' that cannot start any token (linha 2)
Indentação inconsistente (2 vs 3 espaços)bad indentation of a mapping entry (linha 3)Nested mappings are not allowed in compact mappings (linha 2)mapping values are not allowed here (linha 3)
: sem aspas dentro de um valor (url: http://x.com: 8080)bad indentation of a mapping entry (linha 1, col 24)Nested mappings are not allowed in compact mappings (linha 1, col. 6)mapping values are not allowed here (linha 1, col 24)
Aspas duplas não fechadasunexpected end of the stream within a double quoted scalar (última linha)Missing closing "quote (linha 2, col. 8)while scanning a quoted scalar ... found unexpected end of stream (aponta para a aspa de abertura)
*alias para uma âncora não definidaunidentified alias "missing"Unresolved alias (the anchor must be set before the alias): missing (não informa a linha)found undefined alias 'missing'
Flow [ não fechadomissed comma between flow collection entries (linha seguinte)Flow sequence in block collection must be sufficiently indented and end with a ] (linha 2)while parsing a flow sequence ... expected ',' or ']'

Três dicas para ler essas mensagens. Primeiro, mapping values are not allowed here (PyYAML) e bad indentation of a mapping entry (js-yaml) parecem não ter relação, mas são erros irmãos: ambos significam "há um : onde um mapeamento não pode começar", e o Nested mappings are not allowed in compact mappings do eemeli é o mesmo diagnóstico com uma terceira redação. Segundo, o número da linha reportado muda entre os parsers: numa aspa não fechada, o js-yaml aponta para o fim do stream enquanto o PyYAML aponta para a aspa de abertura, então confira tanto a linha reportada quanto o ponto onde a aspa mais próxima abre. Terceiro, no mesmo documento o eemeli costuma apontar uma linha antes do js-yaml, porque reporta onde o mapeamento compacto começou, e não onde ele quebrou.

A forma mais rápida de detectar esses erros é deixar um parser ler o arquivo. Você pode fazer isso sem instalar nada, colando o seu YAML no conversor de YAML para JSON do FormatArc. Se o arquivo for válido, você verá o equivalente em JSON imediatamente. Se não for, o conversor avisa que o documento tem um erro de sintaxe e dá a linha para onde ir: ele de propósito não imprime a mensagem bruta do parser, então, quando você quiser pesquisar pela redação exata que a sua própria toolchain emite, use a tabela acima.

Solução: "It is forbidden to specify block composed value at the same line as key"

Essa é uma inspeção de YAML da família de IDEs JetBrains/IntelliJ (IntelliJ IDEA, PyCharm, GoLand, Rider, DataGrip). O texto exato está definido em YAMLBundle.propertiesAbre em uma nova aba como annotator.same.line.composed.value.message.

A mensagem significa uma coisa só: uma coleção de bloco começou na mesma linha da sua chave. Lendo o código do annotatorAbre em uma nova aba, ele verifica exatamente duas formas: uma sequência de bloco cujo primeiro item divide a linha com a chave, e um mapeamento de bloco cujo primeiro par chave-valor divide a linha com a chave. Nada mais dispara a inspeção.

Forma 1: uma sequência de bloco começando na linha da chave.

# Dispara a inspeção
key: - item1
     - item2

Solução: desça o primeiro item para a linha seguinte.

key:
  - item1
  - item2

Forma 2: um mapeamento de bloco começando na linha da chave.

# Dispara a inspeção
key: sub: value
     sub2: value2

Solução: o mesmo tratamento, quebrar a linha depois dos dois-pontos.

key:
  sub: value
  sub2: value2

Nenhuma das duas formas é implicância do IDE: são erros de YAML. Os parsers também as rejeitam, com um texto próximo ao do IntelliJ. O pacote yaml retorna Unexpected block-seq-ind on same line with key para a forma 1 e Nested mappings are not allowed in compact mappings para a forma 2.

Não é a inspeção de chaves duplicadas. Chaves de mapeamento duplicadas produzem outra mensagem, Key 'x' is duplicated (YAMLDuplicatedKeysInspection.duplicated.key no mesmo bundle). Se a sua IDE diz que uma chave está duplicada, a solução é renomeá-la ou mudá-la de pai, e não tem relação com onde a coleção de bloco começa.

Quando a mensagem aparece em templates Helm ou Jinja válidos. O annotator interrompe a verificação quando o elemento contém fragmentos de template injetados, então um template bem escrito não deveria ser sinalizado. Se ainda assim aparecer, é um falso positivo conhecido — a JetBrains registra isso em issues como IJPL-64437Abre em uma nova aba — e o arquivo não precisa de mudança nenhuma.

Depois de editar, cole o arquivo em YAML para JSON para confirmar que a coleção de bloco agora começa na própria linha. A conversão roda inteiramente no seu navegador — o seu YAML não é enviado para lugar nenhum.

Valide o seu YAML no navegador com o FormatArc

As ferramentas que rodam só no navegador do FormatArc funcionam bem como um linter rápido de YAML:

Resultado da conversão de YAML para JSON mostrando um parse bem-sucedido com diagnósticos por número de linhaResultado da conversão de YAML para JSON mostrando um parse bem-sucedido com diagnósticos por número de linha

  • YAML para JSON — cole o YAML, veja a saída JSON e receba erros com número de linha quando algo estiver errado
  • JSON para YAML — partindo de JSON e quer ver o equivalente em YAML? Use isto para aprender o mapeamento entre os dois formatos
  • Formatador de JSON — formate o JSON que sai do seu YAML

Tudo roda no navegador. Nada sai da sua máquina, então você pode colar com segurança arquivos de config internos ou segredos enquanto faz o debug.

Perguntas frequentes

Posso usar tabs para indentação em YAML?

Não. A especificação do YAML exige espaços, e um caractere de tab literal vai produzir um erro de sintaxe na maioria dos parsers. Configure o seu editor para inserir dois espaços quando você pressionar Tab em um arquivo .yml ou .yaml.

Qual é a diferença entre .yml e .yaml?

Nenhuma. As duas extensões são tratadas de forma idêntica por todos os parsers de YAML. A especificação oficial recomenda .yaml, mas .yml é comum e totalmente suportado.

Sempre preciso de aspas em torno das strings?

Não. O YAML permite que você escreva a maioria das strings sem aspas. Adicione aspas apenas quando o valor seria, de outra forma, parseado como um tipo diferente, ou quando ele começa com um caractere especial, como -, :, [, {, | ou >.

Por que version: 1.0 vira 1?

O YAML parseia 1.0 como um número de ponto flutuante, e algumas ferramentas depois serializam o float como 1. Para mantê-lo como string, use aspas: version: "1.0".

Quantos espaços devo usar para a indentação?

Dois é a convenção usada por Kubernetes, Docker Compose, GitHub Actions e pela maioria dos exemplos que você verá online. Quatro também serve, contanto que você seja consistente dentro de um único arquivo.

Como valido um arquivo YAML sem instalar nada?

Cole-o no conversor de YAML para JSON do FormatArc. Se o YAML for válido, você verá a saída JSON imediatamente. Se não for, a mensagem de erro inclui o número da linha, para que você corrija o problema rapidamente.

Posso escrever vários documentos YAML em um arquivo?

Sim. Separe-os com uma linha contendo apenas ---. É assim que os manifestos do Kubernetes costumam ser agrupados. Um único arquivo YAML pode conter quantos documentos você quiser.

Leitura relacionada

Resumo

  • O YAML usa indentação, e não chaves, para expressar a estrutura
  • Apenas espaços — nunca tabs, e seja consistente
  • Use aspas em strings apenas quando elas seriam mal interpretadas
  • Use comentários, strings de várias linhas e âncoras para tornar os arquivos de config legíveis
  • Valide o seu YAML rapidamente colando-o na ferramenta de YAML para JSON do FormatArc