docker/cli · error · invalidParameterErr
conflicting options: cannot specify both --link-local-ip…
Error message
conflicting options: cannot specify both --link-local-ip and per-network link-local IP addresses
What it means
Thrown by applyContainerOptions when a container is created/run with both the global --link-local-ip flag (which sets copts.linkLocalIPs) and per-network link-local IP addresses embedded inside the --network advanced notation (n.LinkLocalIPs). Docker forbids mixing the legacy global flag style with the newer per-network endpoint notation for the same property, because it cannot decide which one wins for which network. The check is one of a family of mutually-exclusive option guards around lines 812-829.
Solutions
- Pick ONE notation: use either the global --link-local-ip flag OR the per-network link_local_ip=... inside the --network argument, never both.
- If you need different link-local IPs per network, use the advanced per-network notation exclusively and drop --link-local-ip.
- Audit your command/docker-compose for both 'link-local-ip' keys appearing in both the top-level and the networks.* section.
Example fix
// before docker run --network mynet:link_local_ip=169.254.10.11 --link-local-ip 169.254.10.10 alpine // after docker run --network mynet:link_local_ip=169.254.10.11 alpine
Defensive patterns
Strategy: validation
Validate before calling
// Before building the run args, ensure link-local IPs are set via exactly one path.
// allowedNotation: "flag" (global --link-local-ip) or "per-network" (--network name:link_local_ip=...)
func validateLinkLocalIPNotation(globalLinkLocalIPs []string, perNetworkLinkLocalIPs map[string][]string) error {
if len(globalLinkLocalIPs) > 0 {
for _, ips := range perNetworkLinkLocalIPs {
if len(ips) > 0 {
return errors.New("conflicting options: cannot specify both --link-local-ip and per-network link-local IP addresses")
}
}
}
return nil
} Prevention
- Standardize on the advanced --network=name:link_local_ip=... notation in all new code and drop global --link-local-ip.
- When refactoring flag builders, grep for both 'link-local-ip' and 'link_local_ip' to catch mixed usage.
- In templates, make the link-local IP source a single parameter rather than allowing both paths.
When it happens
Trigger: Run/create a container passing both forms: e.g. `docker run --link-local-ip 169.254.10.10 --network mynet:link_local_ip=169.254.10.11 ...`. The guard at opts.go:827 fires because len(n.LinkLocalIPs)>0 (from the advanced notation) AND copts.linkLocalIPs.Len()>0 (from the global flag).
Common situations: Migrating an old script that used --link-local-ip to the advanced --network=name:link_local_ip=... syntax and forgetting to strip the old flag. Copy-pasting compose snippets that mix notations. Templating tools (Helm/Terraform) concatenating flags from multiple sources.
Related errors
- conflicting options: cannot specify both --timeout and…
- conflicting options: cannot specify both --attach and…
- filtering is not supported when specifying a list of…
- conflicting options: cannot specify both --timeout and…
- conflicting options: --no-pause and --pause cannot be used…
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/fdb79c38009e596f.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/container/opts.go:828
func applyContainerOptions(n *opts.NetworkAttachmentOpts, copts *containerOptions) error { //nolint:gocyclo
// TODO should we error if _any_ advanced option is used? (i.e. forbid to combine advanced notation with the "old" flags (`--network-alias`, `--link`, `--ip`, `--ip6`)?
if len(n.Aliases) > 0 && copts.aliases.Len() > 0 {
return invalidParameter(errors.New("conflicting options: cannot specify both --network-alias and per-network alias"))
}
if len(n.Links) > 0 && copts.links.Len() > 0 {
return invalidParameter(errors.New("conflicting options: cannot specify both --link and per-network links"))
}
if n.IPv4Address.IsValid() && copts.ipv4Address != nil {
return invalidParameter(errors.New("conflicting options: cannot specify both --ip and per-network IPv4 address"))
}
if n.IPv6Address.IsValid() && copts.ipv6Address != nil {
return invalidParameter(errors.New("conflicting options: cannot specify both --ip6 and per-network IPv6 address"))
}
if n.MacAddress != "" && copts.macAddress != "" {
return invalidParameter(errors.New("conflicting options: cannot specify both --mac-address and per-network MAC address"))
}
if len(n.LinkLocalIPs) > 0 && copts.linkLocalIPs.Len() > 0 {
return invalidParameter(errors.New("conflicting options: cannot specify both --link-local-ip and per-network link-local IP addresses"))
}
if copts.aliases.Len() > 0 {
n.Aliases = make([]string, copts.aliases.Len())
copy(n.Aliases, copts.aliases.GetSlice())
}
// For a user-defined network, "--link" is an endpoint option, it creates an alias. But,
// for the default bridge it defines a legacy-link.
if container.NetworkMode(n.Target).IsUserDefined() && copts.links.Len() > 0 {
n.Links = make([]string, copts.links.Len())
copy(n.Links, copts.links.GetSlice())
}
if copts.ipv4Address != nil {
if ipv4, ok := netip.AddrFromSlice(copts.ipv4Address.To4()); ok {
n.IPv4Address = ipv4
}
}
if copts.ipv6Address != nil {
if ipv6, ok := netip.AddrFromSlice(copts.ipv6Address.To16()); ok {View on GitHub (pinned to 4f84911bfe)