{"record":{"id":"49aff338a94a0447","repo":"caddyserver/caddy","slug":"s-key-does-not-exist-s","errorCode":null,"errorMessage":"[%s] key does not exist: %s","messagePattern":"\\[(.+?)\\] key does not exist: (.+?)","errorType":"http","errorClass":"APIError","httpStatus":404,"severity":"error","filePath":"admin.go","lineNumber":1293,"sourceCode":"\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tv[part] = append(arr, val)\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tv[part] = val\n\t\t\t\t\t}\n\t\t\t\tcase http.MethodPut:\n\t\t\t\t\tif _, ok := v[part]; ok {\n\t\t\t\t\t\treturn APIError{\n\t\t\t\t\t\t\tHTTPStatus: http.StatusConflict,\n\t\t\t\t\t\t\tErr:        fmt.Errorf(\"[%s] key already exists: %s\", path, part),\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tv[part] = val\n\t\t\t\tcase http.MethodPatch:\n\t\t\t\t\tif _, ok := v[part]; !ok {\n\t\t\t\t\t\treturn APIError{\n\t\t\t\t\t\t\tHTTPStatus: http.StatusNotFound,\n\t\t\t\t\t\t\tErr:        fmt.Errorf(\"[%s] key does not exist: %s\", path, part),\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tv[part] = val\n\t\t\t\tcase http.MethodDelete:\n\t\t\t\t\tif _, ok := v[part]; !ok {\n\t\t\t\t\t\treturn APIError{\n\t\t\t\t\t\t\tHTTPStatus: http.StatusNotFound,\n\t\t\t\t\t\t\tErr:        fmt.Errorf(\"[%s] key does not exist: %s\", path, part),\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdelete(v, part)\n\t\t\t\tdefault:\n\t\t\t\t\treturn fmt.Errorf(\"unrecognized method %s\", method)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// if we are \"PUTting\" a new resource, the key(s) in its path\n\t\t\t\t// might not exist yet; that's OK but we need to make them as\n\t\t\t\t// we go, while we still have a pointer from the level above","sourceCodeStart":1275,"sourceCodeEnd":1311,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/admin.go#L1275-L1311","documentation":"Returned (APIError, HTTP 404) when PATCH targets a map key that does not exist. PATCH is strictly update-only: the final path segment must already be present in the config map. There is no implicit creation with PATCH.","triggerScenarios":"PATCH /config/apps/http/servers/myserver3/listen when 'myserver3' was never created, or patching a key that was deleted by a concurrent client or a config reload that reset the tree.","commonSituations":"Assuming PATCH upserts (RFC-style) when Caddy defines it as update-only; patching after another process replaced the whole config via PUT /config/ or a Caddyfile reload, dropping the key.","solutions":["Create first with PUT (key must not exist), then PATCH","GET the parent path to confirm the key exists before patching","If your workflow replaced the config, re-apply the full desired state instead of patching stale paths"],"exampleFix":"# before\ncurl -X PATCH http://localhost:2019/config/apps/http/servers/myserver3/listen -d '[\":8443\"]'  # 404\n# after\ncurl -X PUT http://localhost:2019/config/apps/http/servers/myserver3/listen -d '[\":8443\"]'","handlingStrategy":"validation","validationCode":"key=\"myserver3\"\nexists=$(curl -s \"http://localhost:2019/config/apps/http/servers\" | jq --arg k \"$key\" 'has($k)')\n[ \"$exists\" = \"true\" ] && curl -X PATCH \"http://localhost:2019/config/apps/http/servers/$key\" -d @body.json \\\n  || curl -X PUT \"http://localhost:2019/config/apps/http/servers/$key\" -d @body.json","typeGuard":null,"tryCatchPattern":"On 404 from PATCH, verify the key against a fresh GET of the parent; create with PUT if it should exist, otherwise fix the stale path.","preventionTips":["PATCH never creates; ensure creation happened first","Re-resolve paths after config reloads or full-config replacements"],"tags":["caddy","admin-api","config","not-found","http-404"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}