docker/cli · error

network : network.external.name and network.name conflict…

Error message

network %s: network.external.name and network.name conflict; only use network.name

What it means

Thrown by LoadNetworks when a network has `external: true` (or `external: { name: ... }`) and BOTH `external.name` (deprecated) and the top-level `name` are set. Compose treats these as mutually exclusive because they both try to rename the external resource.

Solutions

  1. Delete the `external.name` key and keep only `name`.
  2. If you rely on the deprecated form, remove the `name` key entirely.

Example fix

# before
networks:
  dbnet:
    external:
      name: prod-dbnet
    name: prod-dbnet
# after
networks:
  dbnet:
    external: true
    name: prod-dbnet
Defensive patterns

Strategy: validation

Validate before calling

// ensure a network sets at most one of external.name / name
func validateNetworkName(name string, nw map[string]any) error {
    ext, _ := nw["external"]
    var extName string
    switch e := ext.(type) {
    case map[string]any:
        extName, _ = e["name"].(string)
    }
    topName, _ := nw["name"].(string)
    isExternal := ext == true
    if isExternal && extName != "" && topName != "" {
        return fmt.Errorf("network %s: set only one of external.name or name", name)
    }
    return nil
}

Prevention

When it happens

Trigger: A compose file declares a network with `external: { name: foo }` AND `name: bar` under the same network entry. Reached only when `nw.External.External` is true and `External.Name` is non-empty.

Common situations: Migrating from the deprecated `external.name` syntax to `name` and leaving both in place; merging two compose files that each set a different field.

Related errors


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

Appendix: source

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

	}
}

// LoadNetworks produces a NetworkConfig map from a compose file Dict
// the source Dict is not validated if directly used. Use Load() to enable validation
func LoadNetworks(source map[string]any, version string) (map[string]types.NetworkConfig, error) {
	networks := make(map[string]types.NetworkConfig)
	err := Transform(source, &networks)
	if err != nil {
		return networks, err
	}
	for name, nw := range networks {
		if !nw.External.External {
			continue
		}
		switch {
		case nw.External.Name != "":
			if nw.Name != "" {
				return nil, fmt.Errorf("network %s: network.external.name and network.name conflict; only use network.name", name)
			}
			if versions.GreaterThanOrEqualTo(version, "3.5") {
				logrus.Warnf("network %s: network.external.name is deprecated in favor of network.name", name)
			}
			nw.Name = nw.External.Name
			nw.External.Name = ""
		case nw.Name == "":
			nw.Name = name
		}
		nw.Extras = loadExtras(name, source)
		networks[name] = nw
	}
	return networks, nil
}

func externalVolumeError(volume, key string) error {
	return fmt.Errorf(`conflicting parameters "external" and %q specified for volume %q`, key, volume)
}

View on GitHub (pinned to 4f84911bfe)