{"record":{"id":"2061d945ab3f3bc1","repo":"caddyserver/caddy","slug":"adapting-config-using-s-adapter-v","errorCode":null,"errorMessage":"adapting config using %s adapter: %v","messagePattern":"adapting config using (.+?) adapter: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"caddyconfig/load.go","lineNumber":211,"sourceCode":"\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":193,"sourceCodeEnd":222,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/caddyconfig/load.go#L193-L222","documentation":"Returned with HTTP 400 when the resolved config adapter's Adapt() call fails on the request body. For the caddyfile adapter this covers Caddyfile syntax errors, unknown directives/site addresses, and invalid blocks. The error message names the adapter and chains the adapter's own diagnostic, which usually includes the file line number.","triggerScenarios":"POSTing a Caddyfile with syntax errors (unclosed braces, wrong directive order) to /load or /adapt with Content-Type: text/caddyfile; using a directive from a plugin not compiled in; global options block mistakes; environment variable placeholders that fail to expand.","commonSituations":"Editing a Caddyfile by hand and pushing via the admin API without testing; CI pushing a template-rendered Caddyfile where a variable rendered empty; upgrading Caddy where a directive was renamed or removed.","solutions":["Test locally first: caddy validate --config Caddyfile --adapter caddyfile shows the exact line and cause","Use POST /adapt (not /load) to dry-run adaptation without applying the config","Read the chained error — the caddyfile adapter reports line numbers of the offending token"],"exampleFix":"# before\ncurl -X POST http://localhost:2019/load -H 'Content-Type: text/caddyfile' -d @Caddyfile  # fails\n# after\ncaddy validate --config Caddyfile --adapter caddyfile && curl -X POST http://localhost:2019/load -H 'Content-Type: text/caddyfile' -d @Caddyfile","handlingStrategy":"validation","validationCode":"// dry-run adaptation via POST /adapt; only /load on success\nreq, _ := http.NewRequestWithContext(ctx, \"POST\", admin+\"/adapt\", bytes.NewReader(src))\nreq.Header.Set(\"Content-Type\", \"text/caddyfile\")\nresp, err := client.Do(req)\nif err != nil { return err }\nif resp.StatusCode != http.StatusOK {\n    b, _ := io.ReadAll(resp.Body)\n    return fmt.Errorf(\"adaptation failed (fix source before loading): %s\", b)\n}","typeGuard":null,"tryCatchPattern":"if resp.StatusCode == http.StatusBadRequest && strings.Contains(bodyText, \"adapting config using\") {\n    // chained error contains Caddyfile line info; surface it, do not retry\n    return fmt.Errorf(\"caddyfile error: %s\", bodyText)\n}","preventionTips":["Run caddy validate --adapter caddyfile in CI for every Caddyfile change","Use POST /adapt as a staging step before POST /load in automation"],"tags":["admin-api","caddyfile","config-adapter","http-400"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}