What Is YAML? YAML vs JSON, Syntax and Common Indentation Errors

What is YAML and what is it used for?
YAML is a human-friendly data serialization language that expresses structure through indentation instead of braces and stores values as key and value pairs. Because it reads like a tidy outline, developers use it for configuration files, CI pipelines, Docker Compose files and Kubernetes manifests.
Here is a simple analogy. JSON is a meticulous clerk who puts everything into boxes separated by commas. YAML writes the same information as a neat bulleted notebook. As a result, your eyes scan it faster. However, a single misplaced space can change the meaning. So what is YAML in technical terms, which rules make it powerful, and where do developers usually trip up? At Talha Aslan and team, we read YAML files every day in client projects, and in this guide we share the traps we keep seeing in practice.
The name itself is a small joke. Today the acronym officially stands for "YAML Ain't Markup Language". In other words, YAML describes itself as a data language, not a markup language. The rules live in the official YAML specification on yaml.org, and the syntax explanations in this article follow that document.
How does YAML work, and how does a parser read a file?
Put simply, a YAML file is plain text. When a program wants to use it, a library called a parser steps in. The parser reads the text and builds a tree from the indentation and symbols. Then it converts that tree into the native data types of your programming language. For example, Python gives you dictionaries and lists, while JavaScript gives you objects and arrays.
The specification describes three basic building blocks. First comes the mapping, a set of key and value pairs. Second comes the sequence, an ordered list. Finally, there is the scalar, a single value such as text, a number, a date or a boolean. Every YAML file, no matter how large, combines these three structures.
The parser often guesses the type of a scalar on its own. If you skip the quotes, it reads 42 as a number and true as a boolean. This implicit typing makes YAML comfortable to write. On the other hand, it also causes the type traps we cover later in this guide. In short, YAML's strength and its risk come from the same place: the language makes decisions for you.
What is YAML syntax for key and value pairs?
The most basic YAML line contains a key, a colon, a space and a value. For example, when you write name: Talha or port: 8080, the parser treats them as entries in a mapping. The space after the colon matters. If you write port:8080, most parsers read the whole thing as one string.
In practice, keys are usually plain text, but you can also wrap them in quotes. Values can be strings, numbers, booleans, null or another nested structure. To express an empty value, you can write null, use ~ or simply leave the value blank.
- String:
title: Hello world, quotes are optional. - Number:
count: 12orratio: 0.75. - Boolean:
enabled: true, and YAML 1.2 recognizes only true and false. - Null:
note: nullornote: ~. - Comment: the parser ignores everything after the
#sign.
Comment support looks like a minor detail, yet it makes a real difference in team work. You can explain right inside the file why a setting has a particular value. Standard JSON offers no comments. That is why many teams choose YAML for files that people edit by hand.
How do you write lists and nested structures in YAML?
To write a list, you put a dash and a space in front of each item. For example, a server list contains lines such as - web1 and - web2. For short lists, YAML also offers an inline style that looks like JSON: languages: [en, de, tr]. Likewise, you can write a short mapping on one line, such as {name: Ana, age: 30}.
Nesting, in other words, relies entirely on indentation. Lines that you indent further under a key become that key's children. For instance, if you write database: and then add host: localhost and port: 5432 two spaces deeper, the database key now holds a mapping.
You can also combine lists and mappings. In a list of users, each dash starts a new user, and the indented lines below the dash define that user's fields. That gives you the array of objects you know from JSON without any brackets. Still, the most common mistake here is a field that does not line up with its siblings. If one field sits a single space too far left, the parser either throws an error or attaches the data somewhere you did not expect.
As a practical rule, we suggest keeping nesting to three or four levels. Deeper structures hurt readability and raise the risk of indentation errors.
How do you write multi-line strings in YAML?
Multi-line strings are one of the features people love most about YAML. In JSON, you have to encode line breaks with escape characters. YAML instead gives you two block styles: the pipe | and the greater-than sign >.
- Literal block (
|): keeps line breaks exactly as you typed them. Use it for scripts, certificates or any text where layout matters. - Folded block (
>): turns single line breaks into spaces and keeps blank lines as paragraph breaks. It works well for long descriptions. - Chomping indicators:
|-strips the final line break, and|+keeps all trailing breaks. - Indentation: the block content must start deeper than its key, otherwise the block ends.
For example, when you want to run several commands in a CI file, you write run: | and list the commands below it with indentation. Each command then stays on its own line, and the file stays easy to read. On the other hand, a folded block fits perfectly when you want to wrap a long sentence in your editor but store it as a single line.
Specifically, mixing up these two symbols causes silent bugs. The file does not fail; your text simply joins differently than you expected. Therefore we recommend the literal block for command sections almost every time.
What are the indentation rules in YAML?
In YAML, indentation is the structure itself, so you need to know the rules well. The specification allows only space characters for indentation. You can choose how many spaces to use. However, all sibling items on the same level must start in exactly the same column.
- Use spaces for indentation, never tabs.
- Pick one indentation width per project; two spaces is the most common choice.
- Align keys on the same level in the same column.
- Start child items at least one space deeper than their parent.
- Place list dashes either level with the parent or deeper, and stay consistent across the file.
The last point confuses many people. Some teams put list dashes in the same column as the parent key, and others indent them by two spaces. Both styles are valid. Trouble starts when one file mixes the two. In practice, the healthiest approach is to agree on one style and enforce it with a formatter or linter.
We also recommend turning on the option that shows invisible characters in your editor. After all, you cannot tell a space from a tab by eye, so this matters. Once you make them visible, you catch half of the errors while typing.
Why do YAML tab errors happen, and how do you fix them?
The error we meet most often in YAML files comes from tab characters in the indentation. YAML's official specification explicitly forbids tabs for indentation. The reason is simple: different editors display a tab at different widths, so the same file could look like two different structures on two machines.
Meanwhile, the exact error text depends on the parser. Most tools show a similar warning that points to the line and column where they found the tab. Some tools, however, miss the tab and build the wrong structure, and then the problem surfaces much later in a different field. That second case is the more dangerous one.
- Go to the line number in the error message and make the invisible characters at the start of the line visible.
- Run your editor's command that converts tabs to spaces on the whole file.
- Turn on the "insert spaces instead of tabs" setting for YAML files permanently.
- Add an
.editorconfigfile to the project and set space indentation for YAML. - Check the file again with a YAML validator or linter.
One clarification: a tab may still appear inside a value, for example as part of a quoted string. The ban only covers the indentation that defines structure. Even so, the safest habit is to never use tabs in YAML files at all.
What other YAML mistakes do developers make most often?
Beyond tabs, we see a handful of mistakes again and again. Most of them still produce a syntactically valid file. In other words, the parser stays quiet and only the data turns out wrong. For that reason, treat the list below as a review checklist.
- Missing space after the colon:
key:valuebecomes one string. - Colon and space inside a value:
title: Note: importantfails, so quote the value. - Values that start with a hash:
color: #ff0000turns into a comment and leaves the value empty, so use quotes. - Duplicate keys: the specification does not allow the same key twice on one level, yet some parsers silently keep the last one.
- Misaligned list items: a field that sits too far left attaches to the parent level.
- Quote confusion: escape sequences do not work in single quotes, but they do work in double quotes.
Above all, duplicate keys hurt most in long Kubernetes or CI files. Imagine you define the same environment variable near the top and again near the bottom. If the parser stays silent, you have to guess which value wins. That is why adding a linter that catches duplicate keys pays off quickly.
What is the Norway problem, and how do YAML type traps happen?
The Norway problem is YAML's most famous type trap. Imagine a file that lists country codes, and you write NO for Norway. A parser that follows YAML 1.1 rules does not read that value as a string. Instead, it reads it as the boolean false, because YAML 1.1 also treats words such as yes, no, on, off, y and n as booleans.
YAML 1.2 then largely fixed this. Its recommended core schema recognizes only true and false as booleans. Still, many popular libraries keep the older 1.1 behavior. So check your library's own documentation to find out which rule set it follows.
- Version numbers:
version: 1.10can turn into the float 1.1. - Leading zeros: some parsers treat values such as
0755as octal numbers. - Colon-separated numbers: in YAML 1.1,
22:22can become a base-60 integer. - Date-like strings: a value such as
2024-01-01can become a date object. - ZIP codes and phone numbers: leading zeros can disappear.
In practice, the fix is simple: quote every value whose type you are not sure about. Country codes, version strings, ZIP codes, phone numbers and IDs should always get quotes. That way, the parser never has to guess.
What is the difference between YAML and JSON?
YAML and JSON carry the same data model: mappings, lists and scalars. The difference lies in how each one writes that model as text. JSON uses braces, brackets, commas and double quotes in a strict format. RFC 8259, the JSON standard, keeps those rules narrow and clear. YAML, by contrast, relies on indentation and behaves more flexibly.
Here is an interesting detail, too. The YAML 1.2 specification aims to be a superset of JSON. In practice, that means a YAML 1.2 parser can read valid JSON text. The reverse does not hold, since a JSON parser cannot read an indented YAML file.
In day-to-day use, the split looks like this. JSON dominates machine-to-machine data exchange, such as API responses and browser code. YAML shines in configuration files that people edit by hand. For JSON in authentication, see our guide what is JWT. For getting JSON out of AI models, read our structured outputs guide. We do not repeat those topics here.
In short, the choice is about context, not taste. Ask who will write the file, who will read it and how costly an error would be. Those answers point to the right format.
YAML vs JSON vs TOML: which one should you choose?
A third option, TOML, has also become popular for configuration. TOML uses section headers similar to INI files and does not depend on indentation. The table below compares all three formats side by side.
| Feature | YAML | JSON | TOML |
|---|---|---|---|
| Structure defined by | Indentation | Braces and commas | Section headers |
| Comments | Yes (#) | Not in the standard | Yes (#) |
| Multi-line strings | Easy (| and >) | Escape characters | Triple quotes |
| Type ambiguity | High, quotes needed | Low | Low, explicit types |
| Deep nesting | Comfortable | Comfortable but noisy | Gets harder with depth |
| Typical use | CI, Compose, Kubernetes | APIs, browsers, data exchange | Package and app settings |
| Hand editing | Readable, error-prone | Noisy | Readable and safe |
Our rule of thumb goes like this. Use JSON when data travels between programs. Choose YAML when people edit the file by hand and the nesting runs deep. Pick TOML for flat, shallow application settings. Moreover, the tool ecosystem often decides for you; if you use Kubernetes or GitHub Actions, the answer is already YAML.
What is YAML used for in real projects?
Most readers who search for what is YAML have already seen it inside some tool. The most common use cases are configuration files, continuous integration definitions, and container and orchestration tools.
- Application configuration: many web frameworks keep environment settings in YAML files.
- CI/CD pipelines: you define build, test and deploy steps in YAML.
- Docker Compose: one file describes several containers.
- Kubernetes: YAML manifests describe pods, services and deployments.
- Infrastructure automation: server setup playbooks and task lists.
- Front matter: static site generators read title, date and tag fields from YAML at the top of each post.
All of these tools share one trait: the files live in version control, and people edit them. YAML's comments and clean layout add real value here. However, the same files often control production directly, so a small indentation slip can cost a lot. Therefore you should make validation a fixed step in your workflow.
How do you use YAML in CI pipeline files?
Continuous integration means building and testing your code automatically on every change; for the full concept, see our guide what is CI/CD. For many teams, a CI file is the first place where they ask what is YAML at all. Most popular CI services define workflows in YAML files inside the repository.
A typical CI file starts with the trigger, meaning which branch and which event start the run. Next come the jobs. Each job lists the environment it runs in and an ordered set of steps. Because the steps form a list, each one starts with a dash, and you usually write the commands inside a literal block.
The mistake we see most often in CI files is a step field with the wrong alignment. For example, if the run field starts four spaces under the dash instead of two, the parser may attach it to a different level. In that case, the service usually refuses to start the workflow and shows a similar warning about an invalid file.
One more tip: lint the CI file locally before you push it. That shortens the push, wait, fail and fix loop. Also, if you install a Python based linter and hit a conflict with the system package manager, our pip externally managed environment error guide walks you through the fix.
What does YAML look like in a Docker Compose file?
Docker Compose lets you describe an application made of several containers in a single YAML file. If containers are new to you, start with our Docker guide.
A Compose file usually starts with a services key at the top level. Under it, each service appears as a mapping with its own name. Each service then holds fields such as the image name, port mappings, environment variables and mounted volumes. Ports and volumes form lists, while you can write environment variables either as a list or as a mapping.
Type traps show up often in Compose files. For example, if you write a port mapping such as 22:22 without quotes, a parser with YAML 1.1 behavior may read it as a base-60 number. That is why the Docker documentation recommends quoting port values. Likewise, if you want to pass environment values such as true or yes as text, use quotes.
In addition, Compose supports YAML anchors and aliases. You can mark shared settings once with &common and reuse them in other services with *common. That cuts repetition in long files.
Why is YAML so common in Kubernetes manifests?
Kubernetes describes every object that runs in a cluster with a manifest file, and teams write most of those files in YAML. The API itself talks JSON behind the scenes, yet YAML has become the standard for manifests that people write. For the difference in roles between the two tools, read Kubernetes vs Docker.
Specifically, every manifest starts with a few fixed top-level fields: the API version, the object kind, metadata and a spec section that describes the desired state. Because this structure nests deeply, indentation discipline matters a lot here. In addition, you can put several documents in one file with the --- separator; keeping a deployment and a service together is a common pattern.
- The container list starts with a dash, and the fields under it must line up.
- Quote label values that look like numbers or booleans.
- Write resource limits as strings together with their units.
- Test the file with server-side validation on the cluster before you apply it.
In Kubernetes, a YAML mistake often appears as an "unknown field" style message. The usual cause is a field that slipped to the wrong level. So a quick first step is to check which parent the field in the error message sits under.
Is YAML safe, and what should you watch out for?
What is YAML from a security angle? YAML itself is just a data format. However, some parsers support advanced type tags that can build programming language objects from a file. Loading an untrusted YAML file in that full-power mode can open the door to unexpected code. That is why most libraries offer a restricted mode, usually called safe loading.
For example, a popular Python YAML library recommends its safe_load function, which produces only basic types. Libraries in other languages offer a similar safe mode. The rule stays simple: always load external data in safe mode.
- Open YAML from users or third parties only with safe loading.
- Keep passwords and API keys out of YAML files; use environment variables or a secrets manager instead.
- Huge chains of anchors and aliases can blow up memory use, so set size limits.
- Check configuration files for secrets before you commit them to version control.
In short, YAML is safe, but the code that reads it stays safe only with the right settings. The responsibility lies in how you call the parser, not in the file.
How do you validate a YAML file and find errors?
The cheapest place to catch YAML errors is your editor, not production. For that, we recommend a three-layer check: editor, linter and schema.
- Editor support: an editor with a YAML extension highlights indentation, flags tabs and shows syntax errors instantly.
- Linter: it reports duplicate keys, line length, inconsistent indentation and trailing spaces.
- Schema validation: it checks whether the file contains the expected fields and correct types. You can also use JSON Schema for YAML files.
- Tool checks: Compose, Kubernetes and CI services usually ship their own validation commands.
When you debug, first jump to the line and column in the error message. Then compare the alignment of the lines just above and below it. YAML errors often start one line before the reported one. After that, quote suspicious values to rule out type issues.
Another tip: converting the file to JSON teaches you a lot. You see, with explicit brackets, how the parser actually understood your structure.
How can AI coding tools help you write YAML?
In practice, coding assistants do well at writing YAML, because these files repeat familiar patterns. For instance, you can create the skeleton of a Compose file or a CI workflow from a short description. We explain how to run that process with a terminal assistant in our guide what is Claude Code.
Still, we advise against using generated YAML blindly. Assistants sometimes suggest an outdated field name, a key that tools no longer support or wrong indentation. They also miss type traps such as the Norway problem now and then. Therefore run generated files through the same linter and schema checks.
Our own routine looks like this. The assistant writes the first draft, a team member reads the file line by line, and then automated validation runs. That way you gain speed without losing control.
Which checklist should you follow when you write YAML?
We have answered what YAML is, how it works and where it breaks. Now let us turn that into a short list you can use every day. Our team checks these items one by one before we approve a new configuration file.
- Indentation uses spaces only, with no tabs.
- The whole file uses one indentation width.
- Keys on the same level start in the same column.
- Every colon has a space after it.
- Country codes, versions, ZIP codes, ports and IDs sit inside quotes.
- Text values with a hash or a colon sit inside quotes.
- The file contains no duplicate keys.
- Command sections use literal blocks.
- No secrets appear as plain text.
- The file passes linting and schema validation.
This list saves time even for small teams. If you want to set up your configuration files, CI pipelines or deployment process from scratch, we can work together through our custom software development service. If you want to understand how data exchange works on the API side, our article what is an API makes a good next step.
Where should you start learning YAML?
The fastest way to learn YAML is to write a small file, convert it to JSON and look at the result. Try a mapping first, then a list, then a nested structure. Check the parser output at each step. That way you see with your own eyes when indentation changes the meaning.
Next, read the sample files of the tools you use. The official docs for Compose, Kubernetes and CI services contain plenty of examples. They show correct use of both the language and the schema each tool expects. After that, compare the files in your own project with those examples.
Finally, skim the core parts of the specification. You do not need to read all of it; scalar types, block styles and indentation rules are enough. If you want to practice structured data on web pages, our schema generator helps you work with JSON-LD. In short, the answer to what is YAML is brief, but using the language well takes regular practice.



