16.4.1.1 Compose YAML Error
A focused guide to Compose YAML Error, connecting core concepts with practical Docker and container operations.
A Compose YAML error is a parsing or interpretation failure rooted in YAML's own syntax rules, a distinct and sometimes surprising category of mistake separate from Compose's own configuration schema, since several YAML behaviors, type coercion, special character handling, multiline string syntax, can silently produce a different value than what was actually intended without necessarily producing an outright parsing error at all.
Tabs versus spaces
YAML strictly requires spaces for indentation and does not permit tab characters at all, which produces an immediate, clear parsing error if a tab has been inserted, often invisibly, by an editor configured to use tabs by default:
yaml: line 4: found character that cannot start any token
cat -A docker-compose.yml | grep -P '\t'
Checking explicitly for tab characters within the file, since they are visually indistinguishable from spaces in most editors, resolves this specific, common cause directly once identified; configuring an editor to always insert spaces for YAML files specifically prevents this from recurring.
Special characters requiring quotation
Certain characters, particularly a colon followed by a space, a hash symbol, or characters at the start of a value that YAML interprets as having special meaning, need to be quoted explicitly when they appear within a value, since YAML would otherwise interpret them according to its own syntax rules rather than as literal text:
environment:
- MESSAGE=Hello: World
yaml: mapping values are not allowed in this context
environment:
- "MESSAGE=Hello: World"
Wrapping the entire value in quotes when it contains a colon followed by a space resolves this, since YAML otherwise interprets the unquoted colon as introducing a new key-value mapping rather than as literal text within the string.
Boolean and type coercion surprises
YAML interprets several bare words as boolean or null values automatically, which can silently produce an unintended type for a configuration value that was actually meant to be a literal string:
environment:
- FEATURE_FLAG=on
Depending on the specific YAML parser and version in use, a bare on, off, yes, no, true, or false value can be interpreted as a boolean rather than the literal string the author intended, which is particularly relevant for an environment variable value that an application expects to compare as a specific string:
environment:
- FEATURE_FLAG="on"
Quoting any value where this kind of ambiguity is even remotely possible removes the ambiguity entirely, forcing the parser to treat it explicitly as a string regardless of how it might otherwise be interpreted.
Numeric-looking strings losing their leading zeros or formatting
A value that looks numeric to YAML, even if it is meant to be treated as a string by the application consuming it, can be parsed as an actual number, which silently drops formatting like leading zeros:
environment:
- PORT_PREFIX=007
PORT_PREFIX=7
Quoting the value explicitly preserves it exactly as written:
environment:
- PORT_PREFIX="007"
Multiline string syntax differences
YAML supports two distinct styles for multiline string values, each with different whitespace handling, and using the wrong one for a given need produces a string with unexpected extra or missing newlines:
command: |
echo "line one"
echo "line two"
command: >
This text will be
folded into a single
line with spaces.
The | (literal block) style preserves newlines exactly as written, appropriate for a multi-line script; the > (folded block) style joins lines together with spaces, appropriate for a long, single logical line of text broken across multiple lines purely for source readability; using > when newlines actually needed to be preserved produces a command or value that has been unexpectedly collapsed into a single line.
Environment variable interpolation syntax
Compose supports its own variable interpolation syntax, distinct from YAML's own syntax entirely, and confusing the two, or using an unsupported interpolation form, produces either a literal, unsubstituted string or an outright error depending on the specific mistake:
environment:
- DATABASE_URL=postgres://${DB_HOST:db}:5432/app
Invalid interpolation format for "environment" option in service "api": "postgres://${DB_HOST:db}:5432/app"
Compose's interpolation syntax specifically requires a colon followed by a hyphen for a default value (${DB_HOST:-db}), not a bare colon; using the correct, supported syntax resolves this:
environment:
- DATABASE_URL=postgres://${DB_HOST:-db}:5432/app
Validating before relying on the file
Rather than discovering a YAML or interpolation issue only when actually attempting to bring the stack up, validating the file directly and reviewing its fully resolved output catches both outright parsing errors and silent type coercion surprises before they cause a confusing runtime symptom:
docker compose config --quiet
docker compose config | grep -A3 "environment:"
The --quiet flag validates the file without printing the full resolved configuration, useful for a quick pass/fail check, particularly within a CI pipeline step intended to catch a malformed Compose file before it ever reaches an actual deployment attempt.
Using a dedicated YAML linter for early detection
A general-purpose YAML linter, run independently of Compose itself, can catch syntax issues, indentation inconsistency, tab usage, with clearer, more specific error reporting than Compose's own parser sometimes provides, and is a reasonable addition to a pre-commit hook or CI pipeline step:
yamllint docker-compose.yml
Common mistakes
- Using tab characters for indentation, which YAML does not permit at all, producing a parsing error that can be confusing if the tab itself is not visually obvious in the editor being used.
- Leaving a value containing a colon-and-space, a leading number that should remain a string, or a bare boolean-like word unquoted, allowing YAML to silently coerce it into an unintended type.
- Choosing the wrong multiline string style,
|versus>, for a given value, producing unexpected newline collapsing or preservation. - Using an unsupported variable interpolation syntax, such as a bare colon instead of
:-, for a default value expression. - Not validating the Compose file with
docker compose configor a dedicated linter before attempting to bring the stack up, discovering a syntax or coercion issue only through a confusing runtime symptom instead.
Compose YAML errors are resolved by treating YAML's own syntax rules, indentation strictness, special character quoting, type coercion behavior, and multiline string styles, as a distinct layer worth validating explicitly and early, separate from Compose's own configuration schema, since several of the most confusing issues in this category are silent type coercions rather than outright parsing failures that would be caught immediately.