caddyserver/caddy · error

[/%s] array index out of bounds: %s

Error message

[/%s] array index out of bounds: %s

What it means

Thrown while traversing an intermediate array when the numeric index is negative or >= the array length. Unlike the final-segment case, there is no PUT append allowance here: intermediate hops must land on an existing element. The message includes the traversed prefix and the bad index.

Source

Thrown at admin.go:1325

				}
			} else {
				// if we are "PUTting" a new resource, the key(s) in its path
				// might not exist yet; that's OK but we need to make them as
				// we go, while we still have a pointer from the level above
				if v[part] == nil && method == http.MethodPut {
					v[part] = make(map[string]any)
				}
				ptr = v[part]
			}

		case []any:
			partInt, err := parseCanonicalArrayIndex(part)
			if err != nil {
				return fmt.Errorf("[/%s] invalid array index '%s': %v",
					strings.Join(parts[:i+1], "/"), part, err)
			}
			if partInt < 0 || partInt >= len(v) {
				return fmt.Errorf("[/%s] array index out of bounds: %s",
					strings.Join(parts[:i+1], "/"), part)
			}
			ptr = v[partInt]

		default:
			return fmt.Errorf("invalid traversal path at: %s", strings.Join(parts[:i+1], "/"))
		}
	}

	return nil
}

// RemoveMetaFields removes meta fields like "@id" from a JSON message
// by using a simple regular expression. (An alternate way to do this
// would be to delete them from the raw, map[string]any
// representation as they are indexed, then iterate the index we made
// and add them back after encoding as JSON, but this is simpler.)
func RemoveMetaFields(rawJSON []byte) []byte {

View on GitHub (pinned to 50e54ee279)

Solutions

  1. GET the array at the failing prefix to see its actual length, then use a valid 0..len-1 index
  2. Recompute indexes after any DELETE that shifts subsequent elements
  3. Generate paths programmatically from the live config instead of hardcoding indexes

Example fix

# before (only 1 route exists)
curl http://localhost:2019/config/apps/http/servers/myserver/routes/2/handle/0
# after
curl http://localhost:2019/config/apps/http/servers/myserver/routes/0/handle/0
Defensive patterns

Strategy: validation

Validate before calling

prefix="apps/http/servers/myserver/routes"
n=$(curl -s "http://localhost:2019/config/$prefix" | jq 'length')
assert 0 <= idx < n, f'index {idx} out of range for array of {n}'

Try / catch

On out-of-bounds during traversal, GET the prefix from the error message, recompute a valid index, and retry the full path once; persistent failure means your path model is wrong.

Prevention

When it happens

Trigger: GET /config/apps/http/servers/myserver/routes/3/... when the routes array has fewer elements; any path that indexes past the end of an intermediate array such as match sets or handler lists.

Common situations: 0-based vs 1-based confusion; stale indexes after elements were deleted or the config reloaded with fewer entries; paths generated from a template with an unfilled or default index.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/fd477f9e9770096d. Report an issue: GitHub.