nektos/act · error
network %q is specified multiple times
Error message
network %q is specified multiple times
What it means
In the advanced network notation (--network name=net1 with per-network options), each network endpoint is collected into a map keyed by target network name. If the same network target appears twice — e.g. '--network name=net1 --network name=net1' or overlapping long/short forms resolving to the same target — the duplicate key is rejected because Docker cannot attach one endpoint config twice.
Source
Thrown at pkg/container/docker_cli.go:798
} else {
hasNonUserDefined = true
}
if i == 0 {
// The first network corresponds with what was previously the "only"
// network, and what would be used when using the non-advanced syntax
// `--network-alias`, `--link`, `--ip`, `--ip6`, and `--link-local-ip`
// are set on this network, to preserve backward compatibility with
// the non-advanced notation
if err := applyContainerOptions(&n, copts); err != nil {
return nil, err
}
}
ep, err := parseNetworkAttachmentOpt(n)
if err != nil {
return nil, err
}
if _, ok := endpoints[n.Target]; ok {
return nil, fmt.Errorf("network %q is specified multiple times", n.Target)
}
// For backward compatibility: if no custom options are provided for the network,
// and only a single network is specified, omit the endpoint-configuration
// on the client (the daemon will still create it when creating the container)
if i == 0 && len(copts.netMode.Value()) == 1 {
if ep == nil || reflect.ValueOf(*ep).IsZero() {
continue
}
}
endpoints[n.Target] = ep
}
if hasUserDefined && hasNonUserDefined {
return nil, errors.New("conflicting options: cannot attach both user-defined and non-user-defined network-modes")
}
return endpoints, nil
}
View on GitHub (pinned to 4f41128141)
Solutions
- Specify each network exactly once in options
- If combining job-level container options and workflow-level options, deduplicate the --network entries
- Use the advanced form only when you need per-network aliases/IPs, otherwise a single --network suffices
Example fix
# before options: --network name=net1 --network name=net1 # after options: --network name=net1
Defensive patterns
Strategy: validation
Validate before calling
seen := map[string]bool{}
for _, n := range networks {
if seen[n.Target] {
return fmt.Errorf("network %q duplicated", n.Target)
}
seen[n.Target] = true
} Prevention
- Mention each network exactly once in options
- When merging option fragments (workflow + job level), deduplicate --network entries
- Prefer the simple --network form unless per-network options are needed
When it happens
Trigger: Passing the same network more than once via container options: combining a plain --network net1 with an advanced --network name=net1, or literally repeating the advanced form. Detected in act's local parse of container options.
Common situations: Workflow options strings concatenating fragments from multiple sources; migrating from single-network to advanced notation without removing the old flag; YAML anchors duplicating option lines.
Related errors
- network-scoped aliases are only supported for user-defined n
- %s is not a valid mac address
- invalid logging opts for driver %s
- --health-interval cannot be negative
- conflicting options: cannot specify both --mac-address and p
AI-assisted analysis of nektos/act@4f41128141 (2026-08-15).
Data as JSON: /api/errors/8dda876de133fc88.
Report an issue: GitHub.