KhueApps
Home/DevOps/Fixing "The Compose file is invalid" schema errors in Docker

Fixing "The Compose file is invalid" schema errors in Docker

Last updated: October 07, 2025

Overview

“The Compose file is invalid” means your compose.yaml (or docker-compose.yml) violates the Compose file schema: wrong keys, wrong types, bad indentation, or unsupported features. This guide shows quick checks, a minimal working example, and concrete fixes.

Applies to Docker Compose V2 (docker compose) and legacy V1 (docker-compose). V2 ignores the version key and focuses on the Compose Specification.

Quickstart: fastest way to pinpoint issues

  1. Ensure you’re using Compose V2.
    • Run:
      docker compose version
      
  2. Validate and render the full config (merges multiple -f files, resolves env vars):
    docker compose config
    
    • If this fails, the error location is usually printed (path like services.web.ports[0]).
  3. If env substitution might be breaking types, try validation without interpolation:
    docker compose config --no-interpolate
    
  4. Lint YAML syntax (indentation, tabs):
    yamllint compose.yaml
    
  5. Reduce to a minimal file (below) and add sections back until the error reappears.

Minimal working example

A small, valid Compose file (no version key required):

# compose.yaml
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"

Run:

docker compose up -d

If this works in your environment, the issue is in your original file’s structure or keys.

Step-by-step diagnosis

  1. Confirm file names and location

    • Compose auto-detects compose.yaml, compose.yml, docker-compose.yaml, or docker-compose.yml in the current directory. Otherwise pass -f.
    docker compose -f ./path/to/compose.yaml config
    
  2. Check YAML syntax first

    • Replace tabs with spaces; YAML forbids tabs for indentation.
    • Ensure lists use dashes and maps use key: value aligned properly.
  3. Inspect the error path

    • Errors often show a path like services.api.deploy or services.web.ports[0].
    • Verify those keys against the Compose spec expectations (types and allowed fields).
  4. Validate with and without env interpolation

    • Bad or missing env vars can turn numbers/booleans into invalid types.
    docker compose config
    docker compose config --no-interpolate
    
  5. Isolate by commenting

    • Comment out blocks (volumes, networks, deploy) until validation passes; then narrow down.
  6. Check for unknown or misplaced keys

    • Top-level must be: services, volumes, networks, configs, secrets, name, profiles.
    • Inside a service, ensure keys like image, build, ports, environment, depends_on, volumes, healthcheck are correctly nested.
  7. Verify list vs map forms

    • Some sections support both list and map. Use the documented shape consistently.
  8. Update tooling if needed

    • Newer Compose features sometimes require a newer Docker/Compose plugin. Check docker compose version and update if very old.

Common causes and concrete fixes

Symptom or messageLikely causeFix
Additional property xyz is not allowedUnknown key at a levelRemove or move the key to the right level; verify spelling.
services is requiredMissing top-level servicesAdd services: and indent service definitions under it.
services.web.ports must be a listWrong type (map or scalar)Use a YAML list: ports:\n - "8080:80".
services.web.ports[0] invalid typeNon-string port mapping shapeQuote short syntax: "8080:80", or use long syntax object with target/published.
services.app.environment must be a mapping or listWrong env formatUse mapping: environment:\n FOO: "bar" or list: - FOO=bar.
cannot load env fileBad --env-file pathEnsure file exists and uses KEY=VALUE lines, no quotes.
Unknown top-level key: serviceTypoUse services: (plural).
Unsupported option: deploy (in local Compose)Swarm-only fieldsRemove deploy: for local Compose or accept it will be ignored.
Invalid interpolation format${VAR} issuesProvide defaults "${VAR:-value}" or set the variable.
mapping values are not allowed hereYAML indentation/tab issueReplace tabs, fix colon alignment, wrap strings with special characters in quotes.

Correct long syntax examples

  • Ports long syntax:
services:
  web:
    image: nginx:alpine
    ports:
      - target: 80
        published: 8080
        protocol: tcp
  • Environment mapping:
services:
  api:
    image: myapp:latest
    environment:
      APP_ENV: "production"
      WORKERS: "4"
  • Volumes: bind vs named
services:
  db:
    image: postgres:16
    volumes:
      - dbdata:/var/lib/postgresql/data
volumes:
  dbdata:

Pitfalls to avoid

  • Mixing tabs and spaces. Use 2 spaces consistently.
  • Misplaced keys: ports belongs under a service, not top-level.
  • Unquoted values that YAML coerces (on/off, yes/no, 01) into booleans or octal. Quote them.
  • Env substitution yielding empty strings that break types (e.g., published: "${PORT}" where PORT is unset). Provide defaults: ${PORT:-8080}.
  • Using container_port or host_port keys—these are not valid. Use ports short or long syntax.
  • Declaring volumes: as a list of strings at top-level when you need driver/options. Use a map when adding options.
  • Relying on deploy for local Compose behavior. Deploy is for Swarm; Compose may ignore it or flag it.
  • File encoding/line endings issues on Windows. Prefer UTF-8 with LF; use a proper editor or dos2unix.

Performance notes

  • Large Compose files validate slower. Break into multiple files and use -f base.yaml -f overrides.yaml to keep config readable and maintainable.
  • Reduce env interpolation overhead during validation with docker compose config --no-interpolate when debugging.
  • Prefer maps for top-level volumes and networks if you need options; this avoids repeated long lists and speeds edits.
  • Avoid excessive anchors/aliases for critical sections if teammates’ editors mis-handle them; readability reduces error-prone edits.
  • Keep images pinned to tags/digests to reduce unexpected changes that trigger cascading edits.

Tiny FAQ

  • Do I need the version key?

    • No. Compose V2 ignores version. Omit it to avoid confusion.
  • Which file name should I use?

    • Prefer compose.yaml. docker-compose.yml is still recognized.
  • How do I validate without starting containers?

    • Use docker compose config (and --no-interpolate if needed). You can also run docker compose up --dry-run to check planning without changes.
  • Why does deploy cause warnings?

    • deploy is for Swarm. Local Compose ignores much of it and might flag options as unsupported.
  • How do I pass env files safely?

    • Use --env-file .env or env_file: in a service. Ensure KEY=VALUE lines, no quotes or spaces around =.

Summary checklist

  • [ ] File named correctly (compose.yaml) or passed via -f
  • [ ] Valid YAML (no tabs, correct indentation)
  • [ ] Top-level keys: services, volumes, networks, etc.
  • [ ] Service keys valid and correctly typed
  • [ ] Env vars resolved (or defaults provided)
  • [ ] docker compose config passes before up

Series: Docker

DevOps