Code Beautifier
services.web.ports contains an invalid type, it should be a string

Fix "ports contains an invalid type" in Docker Compose

An unquoted port like 22:22 is read by YAML as a base-60 number, so Compose gets an integer where it needs a string. Why every port should be quoted.

Input that triggers it

docker run -d --name web -p 22:22 -p 80:80 nginx:1.27
Draft saved locally.

Local workspace

Named projects in IndexedDB · Local only — never synced to our servers. Worksp

Open manager

Batch workspace

Format multiple files locally in one run.

shell
compose.yamlyaml

What the error means

Compose validates each service against a schema before it does anything. services.web.ports contains an invalid type, it should be a string, number (the exact list of accepted types varies by version) means the value it found under ports for the web service was neither of those — typically because YAML had already turned the port mapping into something else before Compose saw it.

The culprit is YAML 1.1, which many parsers still implement. In that version, 22:22 is a sexagesimal (base-60) integer: 22 × 60 + 22 = 1342. So an unquoted - 22:22 under ports arrives at Compose as the integer 1342, which is not a valid mapping, and the schema check fails. Mappings like 8080:80 and 80:80 survive only because the first number is out of the base-60 digit range on some parsers and not others, which is why the failure looks random.

Why it happens

  • An unquoted port mapping with both sides below 60, most famously 22:22 for SSH.
  • A hand-written Compose file converted from a docker run command without quoting the ports.
  • A templating step that emits the value unquoted even when the source was quoted.
  • A parser that applies YAML 1.1 rules, which includes the one used by Compose itself in many versions; YAML 1.2 dropped base-60, but you cannot assume which version you are running.

How to fix it

  1. Paste the docker run command into the converter above. Every port mapping in the output is quoted, and so is every environment value, for the same reason: DEBUG=true must stay the string "true", not become a boolean.
  2. In an existing file, add quotes around each entry under ports: - "22:22".
  3. Quote environment values that YAML could reinterpret: anything that looks like a number, a boolean (yes, no, on, off, true, false), or a time.
  4. Validate the file with YAML Validator in YAML 1.1 mode, which warns about exactly these ambiguous scalars.

The converted example:

services:
  web:
    image: nginx:1.27
    container_name: web
    ports:
      - "22:22"
      - "80:80"

If it still fails

  • The long-form port syntax avoids the problem entirely: - target: 22, published: 22 on separate keys, each a plain integer.
  • Paste the Compose file into YAML to JSON and look at the ports array: if you see 1342 instead of "22:22", a quote is still missing.
  • The same base-60 trap bites version: 3.8 (a float, fine) versus a value like 10:30 in a cron schedule elsewhere in the file.

Related errors