This YAML parsing error occurs when Docker Compose cannot interpret your docker-compose.yml file due to malformed syntax. The most common causes are incorrect indentation, tabs instead of spaces, or invisible characters from copy-pasting. The fix usually involves correcting the whitespace at the line number indicated in the error.
When Docker Compose displays "yaml: line X: did not find expected key," it means the YAML parser encountered unexpected syntax while reading your docker-compose.yml file. YAML is a whitespace-sensitive format, and even small formatting errors can break parsing. The "did not find expected key" message specifically indicates that the parser was expecting a key-value pair (like `image: nginx`) but found something else instead. This often happens when: - A line has incorrect indentation, breaking the expected structure - A key is missing its colon or value - There's a tab character where spaces are required - Invisible characters from copy-pasting are present in the file The line number in the error message points to where the parser got confused, though the actual problem may be on a previous line that set up an incorrect context.
The error message includes a line number. Open your docker-compose.yml and navigate to that line:
# View the file with line numbers
cat -n docker-compose.yml
# Or use a text editor that shows line numbers
code docker-compose.yml
nano -l docker-compose.yml
vim docker-compose.ymlNote that the actual problem might be on a line before the reported line number, as YAML errors can cascade.
YAML does not allow tabs for indentation - only spaces are valid. Find and replace any tabs:
Check for tabs:
# Show tabs as ^I
cat -A docker-compose.yml | head -20
# Find lines with tabs
grep -n $'\t' docker-compose.ymlReplace tabs with spaces:
# Using sed (creates backup)
sed -i.bak 's/\t/ /g' docker-compose.yml
# Using expand command
expand -t 2 docker-compose.yml > temp.yml && mv temp.yml docker-compose.ymlIn vim:
:set expandtab
:retabYAML uses consistent indentation (typically 2 spaces) to define structure. All items at the same level must have identical indentation:
Correct structure:
version: '3.8'
services: # No indent - root level
web: # 2 spaces - service level
image: nginx # 4 spaces - property level
ports: # 4 spaces - same as image
- "8080:80" # 6 spaces - list item
environment:
- NODE_ENV=productionCommon mistakes:
# WRONG - services indented after version
version: '3.8'
services: # Should have no indent
# WRONG - inconsistent indentation
services:
web:
image: nginx
ports: # 3 spaces instead of 4
- "8080:80"YAML requires a space after colons in key-value pairs and after dashes in list items:
Fix key-value pairs:
# WRONG
image:nginx
container_name:myapp
# CORRECT
image: nginx
container_name: myappFix list items:
# WRONG
ports:
-8080:80
-443:443
# CORRECT
ports:
- 8080:80
- 443:443Even environment variables need proper spacing:
# WRONG
environment:
-NODE_ENV=production
# CORRECT
environment:
- NODE_ENV=productionCopy-pasting from websites, PDFs, or documentation can introduce invisible Unicode characters that break YAML parsing:
Detect invisible characters:
# Show all non-printable characters
cat -v docker-compose.yml | head -20
# Check for specific Unicode issues
file docker-compose.yml
# Should show: "ASCII text" or "UTF-8 Unicode text"Fix by retyping or cleaning:
# Remove non-ASCII characters (be careful with intentional Unicode)
LC_ALL=C tr -cd '\11\12\15\40-\176' < docker-compose.yml > clean.yml
mv clean.yml docker-compose.yml
# Or use iconv to clean up
iconv -f utf-8 -t ascii//TRANSLIT docker-compose.yml > clean.ymlThe safest approach is often to manually retype the problematic line.
Use Docker Compose's built-in validation to check your file:
# Validate and show parsed config
docker compose config
# Or with older docker-compose
docker-compose configIf the file is valid, this command outputs the fully parsed and normalized configuration. If there are errors, it shows exactly what's wrong.
Using online validators:
You can also paste your YAML into validators like:
- yamllint.com
- codebeautify.org/yaml-validator
These tools often provide more detailed error messages about what's wrong.
When the error is hard to find, use a divide-and-conquer approach:
# Start with minimal valid file
version: '3.8'
services:
web:
image: nginxThen add sections back gradually:
1. Run docker compose config after each addition
2. When it breaks, the last addition contains the problem
3. Comment out half of that section
4. Keep narrowing down until you find the exact line
# Use comments to disable sections
services:
web:
image: nginx
# ports:
# - "8080:80"
# environment:
# - NODE_ENV=productionEnvironment variables can be specified two ways, and mixing them incorrectly causes errors:
List syntax (with dashes):
environment:
- NODE_ENV=production
- DEBUG=false
- PORT=3000Dictionary syntax (key-value pairs):
environment:
NODE_ENV: production
DEBUG: "false"
PORT: "3000"WRONG - mixing both:
# This causes "did not find expected key"
environment:
- NODE_ENV=production
DEBUG: false # Can't mix list and dictPick one style and use it consistently within each environment block.
Understanding YAML structure:
YAML represents data as nested key-value pairs and lists. The "did not find expected key" error means the parser expected a key (like image: or ports:) but found something else - typically a value or malformed syntax where a key should be.
Line number accuracy:
The line number in YAML errors isn't always where the problem is. The parser reports where it got confused, not where the mistake was made. For example, forgetting to close a list properly on line 10 might cause an error on line 15.
Editor configuration:
Configure your editor to help prevent YAML issues:
// VS Code settings.json
{
"[yaml]": {
"editor.insertSpaces": true,
"editor.tabSize": 2,
"editor.autoIndent": "advanced"
}
}Docker Compose version differences:
Different Compose file versions have different valid keys:
- Version 2.x uses links, volumes_from
- Version 3.x deprecated some keys, added deploy
- Compose Specification (no version) is the modern standard
Using a key from the wrong version can trigger parsing errors.
YAML anchors and aliases:
Advanced YAML features like anchors (&) and aliases (*) can cause confusing errors if malformed:
x-common: &common
restart: always
services:
web:
<<: *common # Merge anchor
image: nginxMulti-line strings:
Multi-line values need proper syntax:
# Literal block (preserves newlines)
command: |
echo "hello"
echo "world"
# Folded block (joins lines)
description: >
This is a long
description that
becomes one lineimage operating system "linux" cannot be used on this platform
How to fix 'image operating system linux cannot be used on this platform' in Docker
manifest unknown: manifest unknown
How to fix 'manifest unknown' in Docker
cannot open '/etc/passwd': Permission denied
How to fix 'cannot open: Permission denied' in Docker
Error response from daemon: failed to create the ipvlan port
How to fix 'failed to create the ipvlan port' in Docker
toomanyrequests: Rate exceeded for anonymous users
How to fix 'Rate exceeded for anonymous users' in Docker Hub