{"record":{"id":"a06a8f254777d974","repo":"caddyserver/caddy","slug":"cannot-use-duplicate-server-name-s","errorCode":null,"errorMessage":"cannot use duplicate server name '%s'","messagePattern":"cannot use duplicate server name '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"caddyconfig/httpcaddyfile/serveroptions.go","lineNumber":367,"sourceCode":"// applyServerOptions sets the server options on the appropriate servers\nfunc applyServerOptions(\n\tservers map[string]*caddyhttp.Server,\n\toptions map[string]any,\n\t_ *[]caddyconfig.Warning,\n) error {\n\tserverOpts, ok := options[\"servers\"].([]serverOptions)\n\tif !ok {\n\t\treturn nil\n\t}\n\n\t// check for duplicate names, which would clobber the config\n\texistingNames := map[string]bool{}\n\tfor _, opts := range serverOpts {\n\t\tif opts.Name == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif existingNames[opts.Name] {\n\t\t\treturn fmt.Errorf(\"cannot use duplicate server name '%s'\", opts.Name)\n\t\t}\n\t\texistingNames[opts.Name] = true\n\t}\n\n\t// collect the server name overrides\n\tnameReplacements := map[string]string{}\n\n\tfor key, server := range servers {\n\t\t// find the options that apply to this server\n\t\toptsIndex := slices.IndexFunc(serverOpts, func(s serverOptions) bool {\n\t\t\treturn s.ListenerAddress == \"\" || slices.Contains(server.Listen, s.ListenerAddress)\n\t\t})\n\n\t\t// if none apply, then move to the next server\n\t\tif optsIndex == -1 {\n\t\t\tcontinue\n\t\t}\n\t\topts := serverOpts[optsIndex]","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/caddyconfig/httpcaddyfile/serveroptions.go#L349-L385","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Search all Caddyfile sources (including imported/snippet files) for duplicated 'name <value>' inside servers blocks and make names unique.","If the duplication comes from double-importing a snippet, import it once.","Alternatively drop the explicit name and target servers by listener address."],"exampleFix":"# before (imported twice)\n(mysrv) {\n  servers {\n    name edge\n    timeouts { read_body 10s }\n  }\n}\nimport mysrv\nimport mysrv\n\n# after\n(mysrv) {\n  servers {\n    name edge\n    timeouts { read_body 10s }\n  }\n}\nimport mysrv","handlingStrategy":"validation","validationCode":"# render the fully-imported Caddyfile and check for duplicate server names\ncaddy adapt --config Caddyfile --adapter caddyfile 2>&1 | grep -c \"duplicate server name\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Import shared snippets exactly once; avoid re-importing files that contain global server options.","Prefer listener-address targeting over custom server names unless names are required."],"tags":["caddyfile","server-options","duplicate-name","imports"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}