{"record":{"id":"120bff0f9c0a667d","repo":"caddyserver/caddy","slug":"unrecognized-config-adapter-s","errorCode":null,"errorMessage":"unrecognized config adapter '%s'","messagePattern":"unrecognized config adapter '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"caddyconfig/load.go","lineNumber":206,"sourceCode":"\t\t\tHTTPStatus: http.StatusBadRequest,\n\t\t\tErr:        fmt.Errorf(\"invalid Content-Type: %v\", err),\n\t\t}\n\t}\n\n\t// if already JSON, no need to adapt\n\tif strings.HasSuffix(ct, \"/json\") {\n\t\treturn body, nil, nil\n\t}\n\n\t// adapter name should be suffix of MIME type\n\t_, adapterName, slashFound := strings.Cut(ct, \"/\")\n\tif !slashFound {\n\t\treturn nil, nil, fmt.Errorf(\"malformed Content-Type\")\n\t}\n\n\tcfgAdapter := GetAdapter(adapterName)\n\tif cfgAdapter == nil {\n\t\treturn nil, nil, fmt.Errorf(\"unrecognized config adapter '%s'\", adapterName)\n\t}\n\n\tresult, warnings, err := cfgAdapter.Adapt(body, nil)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"adapting config using %s adapter: %v\", adapterName, err)\n\t}\n\n\treturn result, warnings, nil\n}\n\nvar bufPool = sync.Pool{\n\tNew: func() any {\n\t\treturn new(bytes.Buffer)\n\t},\n}\n","sourceCodeStart":188,"sourceCodeEnd":222,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/caddyconfig/load.go#L188-L222","documentation":"Returned when the subtype of the Content-Type does not match any registered config adapter (GetAdapter returns nil). The adapter name is taken from the part after the slash: text/caddyfile looks up 'caddyfile'. If that adapter is not compiled into the binary or does not exist, the request fails with HTTP 400.","triggerScenarios":"Content-Type: text/caddyfile sent to a custom Caddy build without the caddyfile adapter; typos like text/caddyfil or text/jsonc; using a third-party adapter name (e.g. text/hcl) in a build that lacks the plugin.","commonSituations":"Minimal custom builds (built from source without modules/caddyfile) that still expose the admin API; version drift where an adapter was renamed; scripts written against full distributions but deployed against slim builds.","solutions":["Check available adapters: caddy list-modules --packages caddy.config_adapters or caddy adapt --adapter","Use the official distribution or rebuild with xcaddy including the adapter module","Fix typos in the Content-Type subtype (e.g. text/caddyfile, not text/caddy-file)","Send application/json to skip adapters entirely when the body is already Caddy JSON"],"exampleFix":"# before\ncurl -X POST http://localhost:2019/load -H 'Content-Type: text/caddy-file' -d @Caddyfile\n# after\ncurl -X POST http://localhost:2019/load -H 'Content-Type: text/caddyfile' -d @Caddyfile","handlingStrategy":"validation","validationCode":"// confirm the adapter exists before using it\nfunc adapterExists(name string) bool {\n    for _, a := range caddyconfig.RegisteredAdapters() { // or parse `caddy list-modules` output\n        if a == name { return true }\n    }\n    return false\n}\nif !adapterExists(adapter) { return fmt.Errorf(\"adapter %q not in this build; rebuild with xcaddy\", adapter) }","typeGuard":null,"tryCatchPattern":"if resp.StatusCode == http.StatusBadRequest && strings.Contains(bodyText, \"unrecognized config adapter\") {\n    return errors.New(\"adapter missing from build — check caddy list-modules --packages caddy.config_adapters\")\n}","preventionTips":["In CI, assert the adapter list of your custom build matches the config formats you deploy","Standardize on text/caddyfile (full distributions) or application/json to avoid adapter lookup entirely"],"tags":["admin-api","config-adapter","content-type","http-400"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}