caddyserver/caddy · error
[%s] array index out of bounds: %s
Error message
[%s] array index out of bounds: %s
What it means
Thrown when addressing an array element by index in the config where the index is outside the array: negative, or >= len(arr) for GET/POST-style access (PUT may use idx == len(arr) to append at the end, but never greater). The message includes the offending path and index.
Source
Thrown at admin.go:1221
traverseLoop:
for i, part := range parts {
switch v := ptr.(type) {
case map[string]any:
// if the next part enters a slice, and the slice is our destination,
// handle it specially (because appending to the slice copies the slice
// header, which does not replace the original one like we want)
if arr, ok := v[part].([]any); ok && i == len(parts)-2 {
var idx int
if method != http.MethodPost {
idxStr := parts[len(parts)-1]
idx, err = parseCanonicalArrayIndex(idxStr)
if err != nil {
return fmt.Errorf("[%s] invalid array index '%s': %v",
path, idxStr, err)
}
if idx < 0 || (method != http.MethodPut && idx >= len(arr)) || idx > len(arr) {
return fmt.Errorf("[%s] array index out of bounds: %s", path, idxStr)
}
}
switch method {
case http.MethodGet:
err = enc.Encode(arr[idx])
if err != nil {
return fmt.Errorf("encoding config: %v", err)
}
case http.MethodPost:
if ellipses {
valArray, ok := val.([]any)
if !ok {
return fmt.Errorf("final element is not an array")
}
v[part] = append(arr, valArray...)
} else {
v[part] = append(arr, val)View on GitHub (pinned to 50e54ee279)
Solutions
- GET the parent array first and confirm its length; valid GET/DELETE/PATCH indices are 0..len-1
- For PUT, len(arr) is valid and appends; anything larger is rejected
- If elements were removed concurrently, re-fetch and recompute the index
Example fix
# before (only 2 routes exist) curl -X DELETE http://localhost:2019/config/apps/http/servers/myserver/routes/3 # after curl -X DELETE http://localhost:2019/config/apps/http/servers/myserver/routes/1
Defensive patterns
Strategy: validation
Validate before calling
parent="http://localhost:2019/config/apps/http/servers/myserver/routes" n=$(curl -s "$parent" | jq 'length') idx=1 [ "$idx" -ge 0 ] && [ "$idx" -lt "$n" ] && curl "$parent/$idx"
Prevention
- Always fetch array length before indexing
- PUT may use index == length to append; GET/DELETE/PATCH may not
When it happens
Trigger: GET /config/apps/http/servers/myserver/routes/5 when only 2 routes exist; DELETE with index == len(arr); negative indices like .../routes/-1.
Common situations: Off-by-one errors assuming 1-based indexing (Caddy is 0-based); stale index after another client deleted an element; using PUT index len(arr)+1 expecting append.
Related errors
- [/%s] invalid array index '%s': %v
- [/%s] array index out of bounds: %s
- decoding request body: %w, at offset %d
- decoding request body: %w
- [%s] invalid array index '%s': %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/ead8556c5a245188.
Report an issue: GitHub.