caddyserver/caddy · error
no traversable path
Error message
no traversable path
What it means
Returned by unsyncedConfigAccess when the config path, after trimming leading and trailing slashes, is the empty string. This guards the traversal splitter before it starts; with an empty path there is nothing to walk in the config tree. It indicates the caller asked for the root in a way the handler does not accept.
Source
Thrown at admin.go:1180
// 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 array
// and means that the user wants to expand the elements
// in the payload array and append each one into the
// destination array, like so:
// array = append(array, elems...)
// This special case is handled below.
ellipses := parts[len(parts)-1] == "..."
if ellipses {
parts = parts[:len(parts)-1]View on GitHub (pinned to 50e54ee279)
Solutions
- Pass a real config sub-path such as apps/http/servers instead of an empty or slash-only string
- If you want the whole config, GET /config/ rather than constructing an empty-path request
Example fix
// before err := unsyncedConfigAccess(http.MethodGet, "/", nil, &buf) // after err := unsyncedConfigAccess(http.MethodGet, "apps/http/servers", nil, &buf)
Defensive patterns
Strategy: validation
Validate before calling
clean = path.strip('/')
assert clean, 'path must address a config subtree'
unsyncedConfigAccess(method, clean, body, out) # Go, internal callers Prevention
- Internal callers: reject empty or slash-only paths at the call site
- HTTP users: GET /config/ for the whole tree instead of degenerate paths
When it happens
Trigger: Passing a path of "/", "//", or "" to the internal config access (as the admin API does when a request targets only the base, e.g. via certain /load or internal dispatch forms).
Common situations: Code calling unsyncedConfigAccess directly with a degenerate path; clients hitting the wrong endpoint so the leftover path is empty. Rarely seen by pure HTTP users because the admin router routes '/' to different handlers.
Related errors
- path missing
- [%s] invalid array index '%s': %v
- [/%s] invalid array index '%s': %v
- invalid traversal path at: %s
- unknown object ID '%s'
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/3cf9e21a842841c2.
Report an issue: GitHub.