nektos/act · error
invalid range format for --expose: %w
Error message
invalid range format for --expose: %w
What it means
Values from --expose may be a single port with optional protocol (<port>/tcp) or a range (<start>-<end>/tcp). Each entry is parsed with network.ParsePortRange; invalid syntax — non-numeric ports, reversed ranges (9000-80), out-of-range port numbers (>65535), or malformed protocol suffixes — fails with this wrapped error.
Source
Thrown at pkg/container/docker_cli.go:481
}
// Add published ports as exposed ports.
exposedPorts := network.PortSet{}
for port := range ports {
p, err := network.ParsePort(string(port))
if err != nil {
return nil, err
}
exposedPorts[p] = struct{}{}
}
// Merge in exposed ports to the map of published ports
for _, e := range copts.expose.GetSlice() {
// support two formats for expose, original format <portnum>/[<proto>]
// or <startport-endport>/[<proto>]
pr, err := network.ParsePortRange(e)
if err != nil {
return nil, fmt.Errorf("invalid range format for --expose: %w", err)
}
// parse the start and end port and create a sequence of ports to expose
// if expose a port, the start and end port are the same
for p := range pr.All() {
exposedPorts[p] = struct{}{}
}
}
// validate and parse device mappings. Note we do late validation of the
// device path (as opposed to during flag parsing), as at the time we are
// parsing flags, we haven't yet sent a _ping to the daemon to determine
// what operating system it is.
devices := copts.devices.GetSlice()
deviceMappings := make([]container.DeviceMapping, 0, len(devices))
cdiDeviceNames := make([]string, 0, len(devices))
for _, device := range devices {
if cdi.IsQualifiedName(device) {
cdiDeviceNames = append(cdiDeviceNames, device)View on GitHub (pinned to 4f41128141)
Solutions
- Use plain '<port>' or '<start>-<end>' with optional '/tcp' or '/udp': --expose 8080 or --expose 3000-3005/tcp
- Fix reversed ranges to low-high
- Keep ports within 1-65535
- Remember --expose only opens the port inside the container network; use -p for host publishing
Example fix
# before options: --expose 8080-80 # after options: --expose 80-8080/tcp
Defensive patterns
Strategy: validation
Validate before calling
for _, e := range exposeList {
if _, err := network.ParsePortRange(e); err != nil {
return fmt.Errorf("bad --expose value %q: %w", e, err)
}
} Type guard
func isValidExpose(s string) bool {
_, err := network.ParsePortRange(s)
return err == nil
} Prevention
- Use <port> or <start>-<end> with optional /tcp|/udp only
- Keep ranges low-high and ports <= 65535
- Don't reuse firewall or URL-style port syntax in --expose
When it happens
Trigger: Passing --expose in container/job options such as '--expose 80-8080-tcp', '--expose tcp://80', '--expose 70000', or '--expose 8080-80'. Parsing happens client-side in act's container option parser before any daemon call.
Common situations: Confusing --expose with -p publish syntax (protocol://host:container forms); ranges written high-low; copy-paste from firewall rules using 65536+ values; YAML coercing '80' to something unexpected.
Related errors
- %s is not a valid mac address
- invalid value: %d. Valid memory swappiness range is 0-100
- invalid publish opts format (should be name=value but got '%
- invalid logging opts for driver %s
- invalid --security-opt: %q
AI-assisted analysis of nektos/act@4f41128141 (2026-08-15).
Data as JSON: /api/errors/498f812fbcb4c492.
Report an issue: GitHub.