{"record":{"id":"c4121267ec7c1c2d","repo":"caddyserver/caddy","slug":"loading-certificates-with-automate-requires-arra","errorCode":null,"errorMessage":"loading certificates with 'automate' requires array of strings, got: %T","messagePattern":"loading certificates with 'automate' requires array of strings, got: %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddytls/tls.go","lineNumber":240,"sourceCode":"\t// certificate loaders\n\tval, err := ctx.LoadModule(t, \"CertificatesRaw\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"loading certificate loader modules: %s\", err)\n\t}\n\tfor modName, modIface := range val.(map[string]any) {\n\t\tif modName == \"automate\" {\n\t\t\t// special case; these will be loaded in later using our automation facilities,\n\t\t\t// which we want to avoid doing during provisioning\n\t\t\tif automateNames, ok := modIface.(*AutomateLoader); ok && automateNames != nil {\n\t\t\t\tif t.automateNames == nil {\n\t\t\t\t\tt.automateNames = make(map[string]struct{})\n\t\t\t\t}\n\t\t\t\trepl := caddy.NewReplacer()\n\t\t\t\tfor _, sub := range *automateNames {\n\t\t\t\t\tt.automateNames[repl.ReplaceAll(sub, \"\")] = struct{}{}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn fmt.Errorf(\"loading certificates with 'automate' requires array of strings, got: %T\", modIface)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tt.certificateLoaders = append(t.certificateLoaders, modIface.(CertificateLoader))\n\t}\n\n\t// using the certificate loaders we just initialized, load\n\t// manual/static (unmanaged) certificates - we do this in\n\t// provision so that other apps (such as http) can know which\n\t// certificates have been manually loaded, and also so that\n\t// commands like validate can be a better test\n\tcertCacheMu.RLock()\n\tmagic := certmagic.New(certCache, certmagic.Config{\n\t\tStorage: ctx.Storage(),\n\t\tLogger:  t.logger,\n\t\tOnEvent: t.onEvent,\n\t\tOCSP: certmagic.OCSPConfig{\n\t\t\tDisableStapling: t.DisableOCSPStapling,","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddytls/tls.go#L222-L258","documentation":"The special 'automate' entry under tls.certificates must unmarshal to *AutomateLoader, which is defined as a []string of subject names to be managed by automation. The type assertion modIface.(*AutomateLoader) failed (or yielded nil), meaning the JSON value for \"automate\" was not a plain array of strings.","triggerScenarios":"Writing {\"automate\": \"example.com\"} (a bare string), {\"automate\": [{\"subject\": \"example.com\"}]} (array of objects), or any object form under the automate key. Only {\"automate\": [\"example.com\", ...]} is valid.","commonSituations":"Hand-edited JSON where users assume automate takes an object with options; converting from Caddyfile syntax and guessing the JSON shape; copy-paste from configs written for a different fork/schema.","solutions":["Change the automate value to a JSON array of hostnames only","If you need per-name issuer/policy options, move those names into tls.automation.policies subjects instead of the automate loader","Run 'caddy validate' on the config to catch the type error before runtime"],"exampleFix":"// before\n{\"certificates\": {\"automate\": {\"subject\": \"example.com\"}}}\n// after\n{\"certificates\": {\"automate\": [\"example.com\"]}","handlingStrategy":"type-guard","validationCode":"import \"encoding/json\"\n\nvar raw json.RawMessage\njson.Unmarshal(cfg, &raw)\nvar certs map[string]json.RawMessage\njson.Unmarshal(raw, &certs)\nif v, ok := certs[\"automate\"]; ok {\n\tvar names []string\n\tif err := json.Unmarshal(v, &names); err != nil {\n\t\treturn fmt.Errorf(\"automate must be an array of strings\")\n\t}\n}","typeGuard":"func isAutomateArray(v json.RawMessage) bool {\n\tvar names []string\n\treturn json.Unmarshal(v, &names) == nil\n}","tryCatchPattern":null,"preventionTips":["Use 'caddy adapt' to generate correct automate JSON from Caddyfile 'tls internal' style directives","Remember automate accepts only a flat string array"],"tags":["caddy","tls","automate","json","type-mismatch"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}