caddyserver/caddy · error
decoding request body: %w
Error message
decoding request body: %w
What it means
Returned by unsyncedConfigAccess when json.Unmarshal of the request body fails with an error that is not a *json.SyntaxError. Typical causes are unexpected EOF (truncated body) or 'invalid character ... after top-level value' (two JSON documents concatenated). The offset detail is omitted because the error type differs.
Source
Thrown at admin.go:1172
// the operation at path according to method, using body and out as
// needed. This is a low-level, unsynchronized function; most callers
// will want to use changeConfig or readConfig instead. This requires a
// read or write lock on currentCtxMu, depending on method (GET needs
// only a read lock; all others need a write lock).
func unsyncedConfigAccess(method, path string, body []byte, out io.Writer) error {
var err error
var val any
// if there is a request body, decode it into the
// variable that will be set in the config according
// to method and path
if len(body) > 0 {
err = json.Unmarshal(body, &val)
if err != nil {
if jsonErr, ok := err.(*json.SyntaxError); ok {
return fmt.Errorf("decoding request body: %w, at offset %d", jsonErr, jsonErr.Offset)
}
return fmt.Errorf("decoding request body: %w", err)
}
}
enc := json.NewEncoder(out)
cleanPath := strings.Trim(path, "/")
if cleanPath == "" {
return fmt.Errorf("no traversable path")
}
parts := strings.Split(cleanPath, "/")
if len(parts) == 0 {
return fmt.Errorf("path missing")
}
// A path that ends with "..." implies:
// 1) the part before it is an array
// 2) the payload is an arrayView on GitHub (pinned to 50e54ee279)
Solutions
- Ensure the body is exactly one complete JSON document; check Content-Length matches the bytes sent
- Reproduce locally: printf '%s' "$BODY" | python3 -m json.tool to see the exact failure
- If a proxy sits in front of the admin endpoint, bypass it or fix its buffering/rewrite rules
- For truncated uploads, retry the request from scratch rather than resuming
Example fix
# before: two concatenated documents
curl -X PUT --data '{"a":1}{"b":2}' http://localhost:2019/config/x
# after
curl -X PUT --data '{"a":1}' http://localhost:2019/config/x Defensive patterns
Strategy: validation
Validate before calling
printf '%s' "$BODY" | jq -e . >/dev/null && curl -X POST --data-binary "$BODY" http://localhost:2019/config/...
Try / catch
Pre-validate with jq/python; if Caddy still 400s, suspect transport truncation (proxy, timeouts) and resend the identical body once over a direct connection.
Prevention
- Use --data-binary, not -d with concatenated variables
- Ensure exactly one top-level JSON value per request body
When it happens
Trigger: Sending a body that ends mid-JSON (connection cut, Content-Length wrong), or sending two JSON values back to back like '{}{}', or a body that is valid UTF-8-invalid bytes caught by the generic unmarshal path.
Common situations: Client retries that append two payloads; proxy buffering bugs producing duplicated bodies; scripts piping partial file contents into curl; empty-but-nonzero bodies consisting of whitespace/newlines plus garbage.
Related errors
- decoding request body: %w, at offset %d
- final element is not an array
- [%s] invalid array index '%s': %v
- [%s] array index out of bounds: %s
- [/%s] invalid array index '%s': %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/ab971ca00ca96934.
Report an issue: GitHub.