caddyserver/caddy · error
[%s] invalid array index '%s': %v
Error message
[%s] invalid array index '%s': %v
What it means
Thrown during config traversal when the second-to-last path part resolves to an array (the destination), and the final part is used as an array index, but it is not a valid integer. parseCanonicalArrayIndex rejects empty strings and non-numeric values. Example: GET /config/apps/http/servers/myserver/routes/first.
Source
Thrown at admin.go:1216
parts = parts[:len(parts)-1]
}
var ptr any = rawCfg
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 {View on GitHub (pinned to 50e54ee279)
Solutions
- Use a numeric zero-based index, e.g. .../routes/0
- Check the shape first: GET the parent array (e.g. .../routes) and count elements
- Prefer /id/<@id> addressing if you want name-based access to an array element
Example fix
# before curl http://localhost:2019/config/apps/http/servers/myserver/routes/first # after curl http://localhost:2019/config/apps/http/servers/myserver/routes/0
Defensive patterns
Strategy: validation
Validate before calling
last = path.rstrip('/').split('/')[-1]
assert last.lstrip('-').isdigit() and last != '', f'last segment must be an integer index, got {last!r}' Prevention
- Remember Caddy JSON arrays (routes, match sets, handlers) need numeric 0-based indices
- Use /id/<@id> when you want name-based element addressing
When it happens
Trigger: GET/PUT/PATCH/DELETE on /config/... where the last segment addresses an element of an array but is not a number, e.g. .../routes/new or .../routes/ (empty). POST is exempt because it appends.
Common situations: Assuming routes/keys are named maps when they are arrays in Caddy's JSON schema; using a human name or @id where a numeric index is required; trailing slash producing an empty final segment.
Related errors
- [/%s] invalid array index '%s': %v
- invalid traversal path at: %s
- decoding request body: %w, at offset %d
- decoding request body: %w
- no traversable path
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/66d5c8635f3dd05e.
Report an issue: GitHub.