slimtoolkit/slim · error

invalid EXPOSE format: %s

Error message

invalid EXPOSE format: %s

What it means

ParseDockerExposeOpt returns 'invalid EXPOSE format: %s' when an EXPOSE value contains a colon. Docker EXPOSE semantics allow only proto/port specifiers (e.g. '80', '8080/udp'); host-port mappings with colons belong to -p, not EXPOSE. The parser rejects such values up front.

Source

Thrown at pkg/app/master/command/clifvparser.go:61

		case true:
			return DefaultStateArchiveVolumeName
		default:
			return ""
		}
	case "off":
		return ""
	default:
		return flag //should validate if it can be a Docker volume name
	}
}

// based on expose opt parsing in Docker
func ParseDockerExposeOpt(values []string) (map[docker.Port]struct{}, error) {
	exposedPorts := map[docker.Port]struct{}{}

	for _, raw := range values {
		if strings.Contains(raw, ":") {
			return nil, fmt.Errorf("invalid EXPOSE format: %s", raw)
		}

		proto, ports := nat.SplitProtoPort(raw)
		startPort, endPort, err := nat.ParsePortRange(ports)
		if err != nil {
			return nil, fmt.Errorf("invalid port range in EXPOSE: %s / error: %s", raw, err)
		}

		for i := startPort; i <= endPort; i++ {
			portInfo, err := nat.NewPort(proto, strconv.FormatUint(i, 10))
			if err != nil {
				return nil, err
			}

			exposedPorts[docker.Port(portInfo)] = struct{}{}
		}
	}
	return exposedPorts, nil

View on GitHub (pinned to 81940d17fa)

Solutions

  1. Remove the colon/host part: use the container-side port only, e.g. '80' instead of '8080:80'.
  2. Move host mappings to the publish-port option, which is parsed by ParsePortBindings.
  3. Keep protocol suffixes if needed: '53/udp' is valid; '53:53/udp' is not.
  4. Validate expose values in your config generator to reject ':' before reaching this parser.

Example fix

// before
expose := []string{"8080:80"}
// after
expose := []string{"8080"}
publish := []string{"8080:80"} // handled by ParsePortBindings
Defensive patterns

Strategy: validation

Validate before calling

for _, v := range exposeValues {
    if strings.Contains(v, ":") {
        return fmt.Errorf("EXPOSE value %q must not contain ':'; use publish for host mappings", v)
    }
}

Try / catch

ports, err := command.ParseDockerExposeOpt(values)
if err != nil {
    if strings.Contains(err.Error(), "invalid EXPOSE format") {
        return fmt.Errorf("use publish-port for host mappings: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ParseDockerExposeOpt (via GetContainerOverrides) with values like '8080:80' or '127.0.0.1:80:80' that contain ':'.

Common situations: Users copying docker run -p publish syntax into the expose option; confusion between EXPOSE (documentation metadata) and publish (actual port mapping); automated config generated from publish rules.

Related errors


AI-assisted analysis of slimtoolkit/slim@81940d17fa (2026-08-31). Data as JSON: /api/errors/353ba5fd5f76b96b. Report an issue: GitHub.