YAML multiline strings
YAML has two block scalar styles and two chomping modifiers, and one of those combinations is quietly breaking your API key.
Four ways to write a multi-line string
YAML has two block scalar styles and two chomping modifiers, giving four combinations. The choice controls two independent things: whether internal newlines are kept, and what happens to the newline at the end.
| Syntax | Internal newlines | Trailing newline | Use for |
|---|---|---|---|
| | Kept | One kept | Scripts, certificates, log samples |
|- | Kept | Stripped | Keys and tokens that must not end in a newline |
|+ | Kept | All kept | Rare; when trailing blank lines are significant |
> | Folded to spaces | One kept | Long prose wrapped for readability |
>- | Folded to spaces | Stripped | A long single-line value, wrapped in the source |
Literal style: |
Every line break in the block is a line break in the value. This is what you want whenever the newlines are part of the data.
startup: |
#!/bin/sh
set -eu
echo "starting"
exec /usr/bin/app
Produces: "#!/bin/sh\nset -eu\necho \"starting\"\nexec /usr/bin/app\n"
The indentation of the block is stripped — the parser removes the common leading whitespace, so the script does not arrive with two spaces on every line. Extra indentation beyond the common level is preserved, which is how you keep the shape of indented code.
Folded style: >
Single line breaks become spaces. Blank lines become a single line break. Use it to wrap a long sentence in the source file without putting line breaks in the value.
description: >
This service handles checkout requests
and writes them to the order queue.
It retries failed writes three times.
Produces: "This service handles checkout requests and writes them to the order
queue.\nIt retries failed writes three times.\n"
A line that is indented more than the rest of the block is not folded — it keeps its line breaks. This surprises people who indent a bullet list inside a folded block, and it is occasionally useful.
Chomping: the - and + modifiers
By default a block scalar ends with exactly one newline, regardless of how many blank lines follow it. That default is right most of the time and wrong in one important case: secrets.
api_key: |
sk_live_4eC39Hq... # value ends with "\n" — many APIs reject this
api_key: |-
sk_live_4eC39Hq... # no trailing newline — usually what you want
An authentication failure that makes no sense, on a key you have triple-checked, is
very often a trailing newline from a | block that should have been
|-.
What happens on conversion to JSON
You can see this for yourself by pasting a block scalar into
YAML to JSON. All four styles collapse to one JSON string
with \n escapes. The
distinction between literal and folded exists only in the YAML source — by the time the
document is parsed, there is just a string. Converting JSON back to YAML will not
restore your block style; the value comes back as a quoted string with escapes, which
is correct and much harder to read.