caddyserver/caddy · error

cannot use duplicate server name '%s'

Error message

cannot use duplicate server name '%s'

What it means

Global server options can carry an explicit 'name <name>' override so later 'servers <name> { ... }' blocks can target the same server. Before applying options, applyServerOptions rejects two serverOptions entries declaring the same non-empty name, because applying both would silently clobber one config.

Source

Thrown at caddyconfig/httpcaddyfile/serveroptions.go:367

// applyServerOptions sets the server options on the appropriate servers
func applyServerOptions(
	servers map[string]*caddyhttp.Server,
	options map[string]any,
	_ *[]caddyconfig.Warning,
) error {
	serverOpts, ok := options["servers"].([]serverOptions)
	if !ok {
		return nil
	}

	// check for duplicate names, which would clobber the config
	existingNames := map[string]bool{}
	for _, opts := range serverOpts {
		if opts.Name == "" {
			continue
		}
		if existingNames[opts.Name] {
			return fmt.Errorf("cannot use duplicate server name '%s'", opts.Name)
		}
		existingNames[opts.Name] = true
	}

	// collect the server name overrides
	nameReplacements := map[string]string{}

	for key, server := range servers {
		// find the options that apply to this server
		optsIndex := slices.IndexFunc(serverOpts, func(s serverOptions) bool {
			return s.ListenerAddress == "" || slices.Contains(server.Listen, s.ListenerAddress)
		})

		// if none apply, then move to the next server
		if optsIndex == -1 {
			continue
		}
		opts := serverOpts[optsIndex]

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Search all Caddyfile sources (including imported/snippet files) for duplicated 'name <value>' inside servers blocks and make names unique.
  2. If the duplication comes from double-importing a snippet, import it once.
  3. Alternatively drop the explicit name and target servers by listener address.

Example fix

# before (imported twice)
(mysrv) {
  servers {
    name edge
    timeouts { read_body 10s }
  }
}
import mysrv
import mysrv

# after
(mysrv) {
  servers {
    name edge
    timeouts { read_body 10s }
  }
}
import mysrv
Defensive patterns

Strategy: validation

Validate before calling

# render the fully-imported Caddyfile and check for duplicate server names
caddy adapt --config Caddyfile --adapter caddyfile 2>&1 | grep -c "duplicate server name"

Prevention

When it happens

Trigger: Two 'servers' option blocks resolving to the same explicit name — e.g. a snippet containing a named servers block imported twice, or the same named servers block defined at top level and inside an imported file.

Common situations: Importing a shared snippet that contains a named servers block both directly and through another import; refactors that duplicate global option blocks across included files.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/a06a8f254777d974. Report an issue: GitHub.