YAML 03 📄 Scalars, Strings, Quotes, and Folded/Literal Block Scalars (| and >)
A YAML scalar is any value that is not a collection. It can be a string, a number, a boolean, a null, or a timestamp. The scalar’s style—plain, single-quoted, double-quoted, literal, or folded—determines how the parser reads its content and what type it resolves to. The same characters can produce different values depending on the style, which is why quoting is not cosmetic in YAML; it is a type annotation.
This chapter covers the scalar styles and the type resolution rules that make them necessary. It explains why an unquoted NO becomes false in some parsers, why a colon in a URL breaks the parse, and how the block scalar indicators | and > control newline preservation. The sections that follow walk through plain scalars and the 1.1 versus 1.2 resolution split, the quoting styles that override resolution, and the block scalar headers that manage indentation and chomping.
Key point: Plain scalars are implicitly typed by the parser, which means an unquoted value can resolve to a boolean, number, or null instead of a string; quoting forces string type, and block scalars control newline behavior.
Why scalar styles matter
The implicit typing problem. YAML’s plain style applies a resolver to every unquoted scalar. Under YAML 1.1, the resolver treats yes, no, on, off, and their case variants as booleans, and treats ~ and NULL as null . Under YAML 1.2’s core schema, only true/false and case variants resolve to booleans; yes and no remain strings . This version split is the source of the “Norway problem”: a country code NO parses as false in a 1.1 parser, silently losing the string .
The quoting override problem. Quoted scalars are never implicitly typed. A single-quoted 'NO' or double-quoted "NO" is always a string, regardless of the parser’s YAML version . This is the fix for every ambiguity: when a value looks like a boolean, number, or null but is intended as a string, quote it. The quote style determines which escape sequences are available, not whether the value is typed.
The newline preservation problem. Plain and quoted scalars are single-line values. Multi-line strings require block scalar styles, and the choice between | and > determines whether the line breaks in the source become line breaks in the value or spaces. The chomping indicator (-, +, or none) controls the trailing newline. Without these indicators, the parser’s default is to keep one trailing newline, which is often not what the author intended .
a. Plain scalars and implicit type resolution
A plain scalar is written without quotes or block indicators. It is the most readable style and the most dangerous, because the resolver decides its type. The resolution rules differ between YAML 1.1 and 1.2.
# Under YAML 1.1 (PyYAML, many older parsers):
enabled: yes # boolean true
country: NO # boolean false (Norway problem)
value: 0644 # octal integer 420
time: 60:00 # sexagesimal integer 3600
# Under YAML 1.2 core schema:
enabled: yes # string "yes"
country: NO # string "NO"
value: 0644 # decimal integer 644
time: 60:00 # string "60:00"
The table below shows the resolution differences that cause the most production bugs .
| Form | YAML 1.1 | YAML 1.2 (core) |
|---|---|---|
yes / no / on / off | boolean | string |
0644 (bare zero prefix) | octal integer 420 | decimal integer 644 |
60:00 (colon-separated) | sexagesimal integer 3600 | string |
NO (country code) | boolean false | string "NO" |
The practical rule is to quote any plain scalar that could be misread: strings that look like booleans (yes, no, on, off), strings with leading zeros, strings with colons, and strings that are exactly null or ~. The quote costs nothing and eliminates the version dependency.
b. Quoted scalars: single and double
Single-quoted scalars use '...'. The only escape is a doubled single quote '', which represents a literal single quote. No other escape sequences are interpreted; backslashes are literal. Single-quoted style is the safest way to force a string without invoking escape processing.
# Single-quoted: backslashes literal, '' escapes a quote
path: 'C:\Users\name' # literal backslashes
message: 'It''s a test' # contains: It's a test
country: 'NO' # always string
Double-quoted scalars use "...". They support the full escape set: \n for newline, \t for tab, \" for a quote, \\ for a backslash, and Unicode escapes like \u00e9. Double quotes are the correct choice when the value needs embedded control characters that the source cannot contain literally.
# Double-quoted: escape sequences processed
message: "Line one\nLine two" # contains a real newline
quote: "She said \"hello\"" # embedded double quotes
unicode: "\u00e9" # é
Both quote styles suppress implicit typing. A quoted "true" is a string, not a boolean. The choice between them is about escaping needs, not about type.
c. Block scalars: | and > with chomping indicators
Block scalars are for multi-line strings. The header has three parts: the style indicator (| or >), an optional indentation indicator (a digit), and an optional chomping indicator (-, +, or none). The style indicator determines newline handling; the chomping indicator determines what happens to the final line break and trailing empty lines .
The literal style | preserves every line break in the content. The folded style > replaces single line breaks with spaces, but preserves breaks around more-indented lines and empty lines .
# Literal: newlines preserved
script: |
line one
line two
# value: "line one\nline two\n"
# Folded: newlines become spaces
description: >
line one
line two
# value: "line one line two\n"
The chomping indicator controls the trailing newline :
| Indicator | Name | Final newline | Trailing blank lines |
|---|---|---|---|
| none | clip | kept (one) | removed |
- | strip | removed | removed |
+ | keep | kept | kept |
# Strip: no trailing newline
path: |-
/usr/local/bin
# value: "/usr/local/bin"
# Keep: all trailing newlines preserved
poem: |+
line one
# value: "line one\n\n"
The indentation indicator is needed when the first line of content begins with a space, or when the content is empty and the parser cannot infer the indentation level. A |2 means the content is indented two spaces relative to the parent node .
Complete Example Session
# ============================================
# PART 1: PLAIN SCALARS AND THE RESOLUTION TRAP
# ============================================
version: 1.0 # string? number? depends on context
country: NO # YAML 1.1: false; YAML 1.2: "NO"
enabled: yes # YAML 1.1: true; YAML 1.2: "yes"
octal: 0644 # YAML 1.1: 420; YAML 1.2: 644
# ============================================
# PART 2: QUOTING TO FORCE STRING TYPE
# ============================================
country_safe: "NO" # always string
enabled_safe: 'yes' # always string
octal_safe: "0644" # always string
version_safe: "1.0" # always string
# ============================================
# PART 3: SINGLE VS DOUBLE QUOTES
# ============================================
windows_path: 'C:\Users\name' # backslashes literal
multiline_msg: "Line one\nLine two" # \n becomes newline
apostrophe: 'It''s fine' # doubled quote becomes one
# ============================================
# PART 4: LITERAL BLOCK WITH DEFAULT CHOPPING
# ============================================
script: |
#!/bin/bash
echo "start"
# value: "#!/bin/bash\necho \"start\"\n"
# ============================================
# PART 5: LITERAL BLOCK WITH STRIP
# ============================================
path: |-
/usr/local/bin
# value: "/usr/local/bin" (no trailing newline)
# ============================================
# PART 6: FOLDED BLOCK
# ============================================
description: >
This is a long sentence
that becomes one line.
# value: "This is a long sentence that becomes one line.\n"
# ============================================
# PART 7: FOLDED WITH MORE-INDENTED LINE (PRESERVED)
# ============================================
example: >
normal line
indented line
normal again
# value: "normal line\n indented line\nnormal again\n"
The parts covered plain scalar ambiguity, quoting to force strings, the single/double quote distinction, literal block default behavior, strip chomping, folded block behavior, and the more-indented line exception in folded style.
Quick Reference
Scalar Styles
| Style | Syntax | Implicit Typing | Newlines |
|---|---|---|---|
| Plain | value | Yes (parser-dependent) | N/A |
| Single-quoted | 'value' | No | N/A |
| Double-quoted | "value" | No | Escape only |
| Literal | | | No | Preserved |
| Folded | > | No | Folded to spaces |
Chomping Indicators
| Indicator | Trailing Newline | Trailing Blanks |
|---|---|---|
| none (clip) | One | Removed |
- (strip) | None | Removed |
+ (keep) | All | Kept |
YAML 1.1 vs 1.2 Resolution
| Value | 1.1 | 1.2 |
|---|---|---|
yes / no | boolean | string |
on / off | boolean | string |
0644 | octal 420 | decimal 644 |
60:00 | integer 3600 | string |
~ / null | null | null (core schema) |
Best Practices
✅ Do This:
# Quote strings that look like booleans
country: "NO" # ✅
# Quote strings with leading zeros
zip: "01234" # ✅
# Use literal for scripts, folded for prose
script: |
echo "hello" # ✅
# Use strip when trailing newline is unwanted
path: |-
/usr/bin # ✅
❌ Don’t Do This:
# Unquoted ambiguous strings
country: NO # ❌ (1.1: false)
# Unquoted numeric-looking strings
version: 1.10 # ❌ (1.10 → 1.1)
# Folded for code
script: >
echo "hello" # ❌ (newlines lost)
# Literal for prose paragraphs
description: |
Long text that should
be one line. # ❌ (unwanted \n)
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
NO becomes false | YAML 1.1 boolean resolver | Quote as "NO" |
Version 1.10 becomes 1.1 | Number parser strips trailing zero | Quote as "1.10" |
yes/no behavior differs across parsers | 1.1 vs 1.2 schema | Quote or pin parser version |
| Block scalar has extra trailing newline | Default clip chomping | Use |- to strip |
| Folded block loses intended newlines | > folds single breaks | Use | for code and addresses |
Real-World Examples
1. Quoted country code
country: "NO"
2. Quoted version string
version: "1.10"
3. Literal script with strip
run: |-
npm install
npm test
4. Folded description
summary: >
A long description that
should be one line.
5. Single-quoted Windows path
path: 'C:\Users\app'
6. Double-quoted with newline escape
message: "Line one\nLine two"
7. More-indented line in folded block
code: >
before
indented
after
8. Keep trailing blank lines
poem: |+
line one
9. Quoted boolean-looking key
"on": enabled
10. Literal block with explicit indent
source: |2
indented
Visual
Scalar Style Decision
┌─────────────────────────────────────────────────────────┐
│ CHOOSING A SCALAR STYLE │
│ │
│ Is the value multi-line? │
│ │ │
│ ┌────┴────┐ │
│ ▼ ▼ │
│ YES NO │
│ │ │ │
│ ▼ ▼ │
│ Block Is the value ambiguous? │
│ scalar │ │
│ │ ┌────┴────┐ │
│ ▼ ▼ ▼ │
│ code? YES NO │
│ use | │ │ │
│ prose? ▼ ▼ │
│ use > Quote Plain │
│ it scalar │
└─────────────────────────────────────────────────────────┘
| vs > Behavior
┌─────────────────────────────────────────────────────────┐
│ LITERAL | FOLDED > │
│ │
│ line one line one │
│ line two line two │
│ │ │ │
│ ▼ ▼ │
│ "line one\nline two\n" "line one line two\n" │
│ │
│ Newlines preserved Newlines become spaces │
│ Use for code, paths Use for prose │
└─────────────────────────────────────────────────────────┘
Chomping
┌─────────────────────────────────────────────────────────┐
│ CHOPPING INDICATORS │
│ │
│ | clip: "text\n" (one trailing newline) │
│ |- strip: "text" (no trailing newline) │
│ |+ keep: "text\n\n" (all trailing newlines) │
│ │
│ Default is clip. Use strip for paths and commands. │
│ Use keep only when blank lines are meaningful. │
└─────────────────────────────────────────────────────────┘
The Resolution Trap
┌─────────────────────────────────────────────────────────┐
│ PLAIN SCALAR RESOLUTION │
│ │
│ country: NO │
│ │ │
│ ▼ │
│ YAML 1.1 parser → false (Norway problem) │
│ YAML 1.2 parser → "NO" │
│ │
│ country: "NO" │
│ │ │
│ ▼ │
│ Any parser → "NO" (string) │
│ │
│ Quote when the string could be a boolean, number, │
│ or null under any YAML version. │
└─────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| Plain scalar | Implicitly typed; parser-version dependent |
| Single-quoted | String type; '' escapes a quote |
| Double-quoted | String type; full escape set |
| Literal block | | preserves newlines |
| Folded block | > folds single breaks to spaces |
| Clip (default) | One trailing newline |
Strip (-) | No trailing newline |
Keep (+) | All trailing newlines |
| Norway problem | NO → false under YAML 1.1 |
| Resolution fix | Quote ambiguous strings |
Key takeaways:
- Plain scalars are typed by the parser, not by the author. Under YAML 1.1,
yes,no,on,off, and their case variants resolve to booleans;NObecomesfalse. YAML 1.2 restricts boolean resolution totrue/false, but not every parser implements 1.2 . - Quoting forces string type. A single-quoted or double-quoted scalar is never implicitly typed. Quote any value that looks like a boolean, number, null, or timestamp.
|preserves newlines;>folds them. Use literal for code, scripts, and paths; use folded for prose paragraphs that should read as one line .- Chomping controls the trailing newline. The default clip keeps one;
-strips all;+keeps all trailing blank lines . - The version split is not academic. PyYAML and many older parsers follow 1.1; newer parsers follow 1.2. The same unquoted
NOproduces different values, which means the file’s meaning depends on the tool reading it .
Remember: A YAML scalar is not a string by default; it is whatever the parser’s resolver decides it is. Quoting is how you override that decision. Block scalar indicators are how you control newlines for multi-line values. The Norway problem, the octal trap, and the version-number truncation are all consequences of trusting plain scalars with values that look like other types. Quote when the type matters, choose | for code and > for prose, and check the chomping indicator when the trailing newline matters.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!