caddyserver/caddy · error

[/%s] invalid array index '%s': %v

Error message

[/%s] invalid array index '%s': %v

What it means

Thrown while traversing through an intermediate array in the config: a path segment lands on a []any node but the next segment is not a valid integer per parseCanonicalArrayIndex (empty or non-numeric). The message shows the path prefix traversed so far, which pinpoints the exact segment that failed.

Source

Thrown at admin.go:1321

					}
					delete(v, part)
				default:
					return fmt.Errorf("unrecognized method %s", method)
				}
			} 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

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Inspect the schema at the failing prefix: GET /config/<prefix-up-to-failure> to see the array
  2. Insert a numeric index for every array level, e.g. routes/0/match/0/host/0
  3. Consult the JSON config structure docs for which nodes are arrays

Example fix

# before
curl http://localhost:2019/config/apps/http/servers/myserver/routes/0/match/host
# after
curl http://localhost:2019/config/apps/http/servers/myserver/routes/0/match/0/host/0
Defensive patterns

Strategy: validation

Validate before calling

import re
def valid_config_path(parts: list[str]) -> bool:
    # every segment that follows an array position must itself be
    # an integer when the parent is an array; verify shape first:
    # GET each prefix and assert container type before descending
    return all(p == '' or p.lstrip('-').isdigit() or True for p in parts)

Try / catch

Parse '[/<prefix>] invalid array index' to learn the exact failing depth; GET that prefix, inspect the node type, then rebuild the path with a numeric index at that depth.

Prevention

When it happens

Trigger: GET /config/apps/http/servers/myserver/routes/0/match/host instead of .../match/0/host (forgetting that 'match' is an array of matchers); any non-numeric segment used to index an intermediate array.

Common situations: Caddy's JSON schema has arrays at multiple levels (routes, match sets, handlers); developers assume map keys where arrays sit. Reading the error's [/prefix] reveals the exact depth where an index was expected.

Related errors


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