docker/cli · error

invalid type %T for port

Error message

invalid type %T for port

What it means

Thrown by transformServicePort in its per-entry loop. When `ports` is a list, each element must be an int, a string (short syntax), or a map (long syntax). Any other element type (bool, nested list, null) hits this default branch.

Solutions

  1. Make each entry an int (`80`), a string (`"8080:80"`), or a map (`{ target: 80, published: 8080 }`).
  2. Remove stray/null entries introduced by templating.

Example fix

# before
web:
  ports:
    - 80
    - [81]
# after
web:
  ports:
    - 80
    - 81
Defensive patterns

Strategy: type-guard

Validate before calling

func validatePortEntries(ports any) error {
    list, ok := ports.([]any)
    if !ok {
        return nil // outer error 469 handles non-list
    }
    for i, e := range list {
        switch e.(type) {
        case int, string, map[string]any:
        default:
            return fmt.Errorf("ports[%d]: invalid type %T", i, e)
        }
    }
    return nil
}

Type guard

func isPortEntry(v any) bool {
    switch v.(type) {
    case int, string, map[string]any:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: A service has `ports:` as a list containing a non-port element, e.g. `ports: [80, [81]]`, `ports: [true]`, or `ports: [~]`.

Common situations: Bad indentation turning a map into a nested list; templating that injects nulls; mixing port and label entries.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/d9bcd916881cefe4. Report an issue: GitHub.

Appendix: source

Thrown at cli/compose/loader/loader.go:731

		ports := []any{}
		for _, entry := range entries {
			switch value := entry.(type) {
			case int:
				v, err := toServicePortConfigs(strconv.Itoa(value))
				if err != nil {
					return data, err
				}
				ports = append(ports, v...)
			case string:
				v, err := toServicePortConfigs(value)
				if err != nil {
					return data, err
				}
				ports = append(ports, v...)
			case map[string]any:
				ports = append(ports, value)
			default:
				return data, fmt.Errorf("invalid type %T for port", value)
			}
		}
		return ports, nil
	default:
		return data, fmt.Errorf("invalid type %T for port", entries)
	}
}

var transformStringSourceMap TransformerFunc = func(data any) (any, error) {
	switch value := data.(type) {
	case string:
		return map[string]any{"source": value}, nil
	case map[string]any:
		return data, nil
	default:
		return data, fmt.Errorf("invalid type %T for secret", value)
	}
}

View on GitHub (pinned to 4f84911bfe)