YAML 05 ๐ Comments and Multi-Document Streams (— and …)
YAML comments and document markers serve two different purposes. A comment is text the parser ignores; it exists for the human reading the file. A document marker separates one YAML document from the next within a single stream, which is how a file can contain multiple independent configurations without being split into separate files. Both features are small, but both have rules that are easy to get wrong: a # inside a quoted string is not a comment, and a --- inside a block scalar is not a document separator.
This chapter covers the comment syntax, the quoting rule that disables it, the document start marker ---, the document end marker ..., and the multi-document stream pattern that tools like Kubernetes use to bundle related resources. The sections that follow walk through comment placement and the quoted-string exception, the two document markers and their asymmetry, and the multi-document stream behavior that determines how parsers expose each document.
Key point: A # starts a comment only outside quoted scalars, and --- starts a new document while ... ends the current one; both markers must appear at the start of a line with nothing else on it.
Why comments and document streams exist
The documentation problem. YAML is a configuration language, and configuration needs explanation. A replicas: 3 value needs a comment saying why three, and a disabled block needs a comment saying it is disabled. YAML’s comment syntax is simpleโa # followed by textโbut the rule that a # inside a quoted string is not a comment is the one that trips people who write values containing the character . A URL fragment like https://example.com/#section must be quoted, or the parser reads #section as a comment and truncates the value.
The bundling problem. A Kubernetes deployment typically needs a Deployment, a Service, and a ConfigMap. Each is a separate YAML document with its own apiVersion, kind, and metadata. Writing them in one file with --- between them keeps related resources together and lets a single kubectl apply -f command process all of them . Without document markers, the file would be one document with three top-level keys, which is not the structure Kubernetes expects.
The stream semantics problem. A YAML file is not one document; it is a stream of zero or more documents. The --- marker starts a document, and ... ends one . The first document can begin without a marker, and the stream ends at end-of-file. Parsers expose the stream differently: some return only the first document, some return an array, and some require explicit iteration . Knowing which behavior a parser implements is necessary before relying on multi-document files.
a. Comments and the quoted-string exception
A comment begins with # and continues to the end of the line. It can appear on its own line or after a value. Everything from the # onward is ignored by the parser .
# A full-line comment
server:
host: localhost # an inline comment after a value
port: 8080 # comments can align for readability
The exception is quoting. A # inside a single-quoted or double-quoted scalar is part of the string, not a comment . This is how a value that contains the character is preserved.
# The hash is part of the value because the scalar is quoted
url: "https://example.com/page#section"
message: 'Use the # symbol for tags'
Unquoted values containing # are truncated. A plain scalar stops at the space before the hash, and the rest becomes a comment.
# INVALID INTENT: the value is "https://example.com/page", not the fragment
url: https://example.com/page#section
Comments cannot appear inside a block scalar. The # in a literal or folded block is content, not a comment .
script: |
# this is part of the script, not a YAML comment
echo "hello"
b. Document start and end markers
The document start marker is ---. It must appear at the beginning of a line, optionally preceded by whitespace, and nothing else can follow it on that line except a comment . A file can begin with --- or without it; the marker is required only when a second document follows the first.
# Document 1 begins here (marker optional for the first document)
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
---
# Document 2 begins after the marker
apiVersion: v1
kind: Secret
metadata:
name: app-secret
The document end marker is .... It terminates the current document and is used less often than ---. When a stream ends with ..., any content after it is either a new document (if --- follows) or invalid .
# Document ends explicitly
apiVersion: v1
kind: Service
metadata:
name: web
...
The asymmetry matters: --- is common because bundling multiple resources is common; ... is rare because end-of-file serves as an implicit end marker. The ... form appears when a stream needs to signal that the document is complete before the file ends, such as when appending to a file or when a parser needs an explicit terminator.
c. Multi-document streams and parser behavior
A multi-document file is a stream of documents separated by ---. The parser returns each document as an independent root node; the documents do not share anchors, aliases, or merge keys .
# A three-document stream
---
name: first
value: 1
---
name: second
value: 2
---
name: third
value: 3
The same YAML can be parsed as an array of three objects, but each object is a separate document. Anchors defined in one document are not visible in the next.
# INVALID ACROSS DOCUMENTS: the anchor does not carry over
---
defaults: &d
timeout: 30
---
service:
<<: *d # ERROR: unknown anchor in this document
Tools that consume multi-document YAML expect this behavior. Kubernetes applies each document independently, so a Deployment and its Service can reference each other by name but cannot share YAML anchors . The separation is the point: each document is a complete unit that can be validated, applied, or deleted on its own.
Complete Example Session
# ============================================
# PART 1: FULL-LINE AND INLINE COMMENTS
# ============================================
# Application configuration
server:
host: localhost # bind address
port: 8080 # http port
# ============================================
# PART 2: THE QUOTED-HASH EXCEPTION
# ============================================
docs:
base_url: "https://example.com/docs#intro" # hash preserved
tag: 'release#1' # hash preserved
# unquoted_hash: value#comment # would truncate
# ============================================
# PART 3: BLOCK SCALAR WITH HASH (CONTENT, NOT COMMENT)
# ============================================
script: |
#!/bin/bash
echo "start" # this is inside the script
# ============================================
# PART 4: MULTI-DOCUMENT STREAM
# ============================================
---
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: info
---
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
password: c2VjcmV0
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 3
# ============================================
# PART 5: EXPLICIT END MARKER
# ============================================
...
# Content after ... without --- is a parse error
# The ... marker signals the stream is complete
# ============================================
# PART 6: THE PARSED MENTAL MODEL
# ============================================
# Stream: [Document, Document, Document]
# Document 1: { apiVersion: "v1", kind: "ConfigMap", ... }
# Document 2: { apiVersion: "v1", kind: "Secret", ... }
# Document 3: { apiVersion: "apps/v1", kind: "Deployment", ... }
#
# Each document is independent. Anchors do not cross boundaries.
The parts covered comment placement, the quoted-hash exception, hash as block scalar content, a three-document Kubernetes-style stream, the explicit end marker, and the parsed stream model.
Quick Reference
Comment Rules
| Rule | Detail |
|---|---|
| Comment start | # outside quotes |
| Full-line | # comment at any indentation |
| Inline | value # comment |
| Inside quotes | Not a comment |
| Inside block scalar | Content, not comment |
| Tabs in comments | Allowed |
Document Markers
| Marker | Name | Effect |
|---|---|---|
--- | Document start | Begins a new document |
... | Document end | Ends the current document |
| None (first) | Implicit start | First document begins at file start |
| None (end) | Implicit end | Stream ends at EOF |
Multi-Document Behavior
| Aspect | Behavior |
|---|---|
| Document independence | Each is a separate root |
| Anchors across documents | Not visible |
| Parser return | Array/stream of documents |
| Kubernetes use | One resource per document |
Best Practices
โ Do This:
# Space after hash
port: 8080 # http port # โ
# Quote values containing hash
url: "https://example.com/#section" # โ
# Start each bundled document with ---
--- # โ
kind: Service
# Keep each document self-contained
--- # โ
kind: Deployment
โ Don’t Do This:
# Unquoted hash in value
url: https://example.com/#section # โ (truncated)
# Hash inside block scalar treated as comment
script: |
# this is content # โ
(actually correct)
# Anchor across documents
--- # โ
a: &x 1
---
b: *x # โ (unknown anchor)
# Marker not at line start
key: value --- # โ (not a separator)
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
URL truncated at # | Unquoted hash | Quote the value |
| Anchor unknown in next document | Anchors do not cross --- | Define anchors per document |
| Parser returns only first document | Parser does not expose stream | Use a stream-aware API |
--- inside block scalar treated as separator | Block scalar content is not parsed | Indent correctly under | or > |
| Comment after block scalar indicator | Content starts on next line | Put comment above the block |
Real-World Examples
1. Inline comment
replicas: 3 # production minimum
2. Quoted hash in URL
redirect: "https://example.com/#/dashboard"
3. Kubernetes multi-document
---
kind: ConfigMap
---
kind: Secret
4. Explicit document end
kind: Service
...
5. Comment above a block
# startup script
script: |
echo "hello"
6. Hash inside quoted string
color: "#FF0000"
7. Multi-document with no first marker
kind: ConfigMap
---
kind: Secret
8. Document separator with comment
--- # second document
kind: Deployment
9. Block scalar with shebang
script: |
#!/bin/bash
echo "start"
10. Stream of three documents
---
a: 1
---
b: 2
---
c: 3
Visual
Comment Parsing
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ WHERE # IS A COMMENT โ
โ โ
โ port: 8080 # comment โ
โ โ โ โ
โ โ โโโโบ comment starts here โ
โ โโโโบ value ends at space before # โ
โ โ
โ url: "https://x/#frag" โ
โ โ โ
โ โโโโบ quoted: # is part of the value โ
โ โ
โ script: | โ
โ # not a comment โ
โ โ โ
โ โโโโบ block scalar: # is content โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Document Markers
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ STREAM STRUCTURE โ
โ โ
โ --- โโโ start document 1 โ
โ kind: ConfigMap โ
โ โ
โ --- โโโ end 1, start 2 โ
โ kind: Secret โ
โ โ
โ --- โโโ end 2, start 3 โ
โ kind: Deployment โ
โ โ
โ ... โโโ end document 3 โ
โ โ
โ Parser returns: [Doc1, Doc2, Doc3] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Anchor Isolation
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ DOCUMENT BOUNDARY = ANCHOR BOUNDARY โ
โ โ
โ Document 1: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ defaults: &d โ โ
โ โ timeout: 30 โ โ
โ โ service: { <<: *d } โโโ valid here โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ --- โ
โ โ
โ Document 2: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ other: { <<: *d } โโโ ERROR โ โ
โ โ *d is unknown in this document โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Kubernetes Bundling
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ONE FILE, THREE RESOURCES โ
โ โ
โ app.yaml โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ --- โ โ
โ โ kind: ConfigMap โโโ applied first โ โ
โ โ --- โ โ
โ โ kind: Secret โโโ applied second โ โ
โ โ --- โ โ
โ โ kind: Deployment โโโ applied third โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ kubectl apply -f app.yaml โ
โ โ processes each document independently โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| Comment character | # outside quoted scalars |
| Quoted hash | Part of the string, not a comment |
| Block scalar hash | Content, not comment |
| Document start | --- at line start |
| Document end | ... at line start |
| First document marker | Optional |
| Multi-document stream | Documents independent; anchors do not cross |
| Kubernetes pattern | One resource per document |
Key takeaways:
- The
#is a comment only outside quotes. A value containing a URL fragment or a color hex must be quoted, or the parser truncates it at the hash . Inside a block scalar, the#is content, not a comment . ---starts a document;...ends one. The start marker is common because bundling resources is common; the end marker is rare because end-of-file is the implicit end .- Documents in a stream are independent. Anchors, aliases, and merge keys defined in one document are not visible in the next. Each document is a complete unit .
- Kubernetes uses multi-document files to bundle related resources. A Deployment, Service, and ConfigMap can live in one file separated by
---, andkubectl applyprocesses each independently . - Both markers must be at the start of a line. A
---inside a value or mid-line is not a document separator; it is part of the scalar.
Remember: Comments are for humans; document markers are for parsers. A comment disappears; a document marker changes the structure of the stream. The # rule is simple once quoting is understood: outside quotes it starts a comment, inside quotes it is a character. The --- rule is equally simple: at line start it starts a new document, anywhere else it is text. When a URL loses its fragment or a multi-document file returns only one document, check the quoting and the parser’s stream support.
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!