docker/cli · error
cannot merge networks
Error message
cannot merge networks: %w
What it means
Thrown by merge() when mergo.Map fails merging the `Networks` maps of two compose Configs. Analogous to the volumes case: merges map[string]NetworkConfig by key and surfaces a mergo error on incompatible values.
Solutions
- Inspect the wrapped `%w` cause for the offending network key.
- Align the network definition across all `-f` files (external vs managed, same driver).
- Override only scalar fields (name, driver) rather than flipping external on/off across files.
Example fix
# before
# base.yml
networks:
appnet:
driver: bridge
# override.yml
networks:
appnet:
external: true
# after
networks:
appnet:
driver: bridge Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure networks with the same key are structurally compatible before merge.
func validateMergeableNetworks(base, override map[string]types.NetworkConfig) error {
for k, ov := range override {
bv, ok := base[k]
if !ok {
continue
}
if bv.External.External != ov.External.External {
return fmt.Errorf("network %s: external flag differs across files", k)
}
}
return nil
} Try / catch
// Surface the wrapped mergo cause clearly.
if err := cfg.Load(details); err != nil {
var me interface{ Unwrap() error }
if errors.As(err, &me) {
return fmt.Errorf("network merge failed: %w", me.Unwrap())
}
return err
} Prevention
- Don't toggle a network between external and managed across override files.
- Keep driver/IPAM config consistent for shared network keys.
- Preview the merge with `docker compose config`.
When it happens
Trigger: Merging two compose files where the Networks map merge raises a mergo error — typically when override and base define the same network name with structurally incompatible config.
Common situations: One file makes a network external, another defines it with driver/labels; mixing attachable/enable_ipv6 differently across overrides.
Related errors
- cannot merge services
- cannot merge volumes
- version mismatched between two composefiles
- network : network.external.name and network.name conflict…
- invalid type %T for external
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/45d5975f38a12ae1.
Report an issue: GitHub.
Appendix: source
Thrown at cli/compose/loader/merge.go:42
return fn
}
return nil
}
func merge(configs []*types.Config) (*types.Config, error) {
base := configs[0]
for _, override := range configs[1:] {
var errs []error
if services, err := mergeServices(base.Services, override.Services); err != nil {
errs = append(errs, fmt.Errorf("cannot merge services: %w", err))
} else {
base.Services = services
}
if err := mergo.Map(&base.Volumes, &override.Volumes, mergo.WithOverride); err != nil {
errs = append(errs, fmt.Errorf("cannot merge volumes: %w", err))
}
if err := mergo.Map(&base.Networks, &override.Networks, mergo.WithOverride); err != nil {
errs = append(errs, fmt.Errorf("cannot merge networks: %w", err))
}
if err := mergo.Map(&base.Secrets, &override.Secrets, mergo.WithOverride); err != nil {
errs = append(errs, fmt.Errorf("cannot merge secrets: %w", err))
}
if err := mergo.Map(&base.Configs, &override.Configs, mergo.WithOverride); err != nil {
errs = append(errs, fmt.Errorf("cannot merge configs: %w", err))
}
if err := errors.Join(errs...); err != nil {
return nil, errors.Join(fmt.Errorf("failed to merge file %s", override.Filename), err)
}
}
return base, nil
}
func mergeServices(base, override []types.ServiceConfig) ([]types.ServiceConfig, error) {
mergeOpts := []func(*mergo.Config){
mergo.WithAppendSlice,
mergo.WithOverride,View on GitHub (pinned to 4f84911bfe)