juicedata/juicefs · error
Forbidden
Error message
Forbidden
What it means
The JuiceFS WebDAV handler returns HTTP 403 'Forbidden' when a GET request targets a directory while DisallowList is enabled. This prevents clients from browsing directory contents through WebDAV GET requests (which the handler would otherwise translate to PROPFIND). The check happens in ServeHTTP in pkg/fs/http.go before delegating to the underlying WebDAV handler.
Source
Thrown at pkg/fs/http.go:293
}
if userName != h.Username || pwd != h.Password {
http.Error(w, "WebDAV: need authorized!", http.StatusUnauthorized)
return
}
}
// Excerpt from RFC4918, section 9.4:
//
// GET, when applied to a collection, may return the contents of an
// "index.html" resource, a human-readable view of the contents of
// the collection, or something else altogether.
//
// Get, when applied to collection, will return the same as PROPFIND method.
if r.Method == "GET" && strings.HasPrefix(r.URL.Path, h.Handler.Prefix) {
info, err := h.Handler.FileSystem.Stat(context.TODO(), strings.TrimPrefix(r.URL.Path, h.Handler.Prefix))
if err == nil && info.IsDir() {
if h.DisallowList {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
r.Method = "PROPFIND"
if r.Header.Get("Depth") == "" {
r.Header.Add("Depth", "1")
}
}
}
// The next line would normally be:
// http.Handle("/", h)
// but we wrap that HTTP handler h to cater for a special case.
//
// The propfind_invalid2 litmus test case expects an empty namespace prefix
// declaration to be an error. The FAQ in the webdav litmus test says:
//
// "What does the "propfind_invalid2" test check for?...
//View on GitHub (pinned to c9a67b23e8)
Solutions
- If directory browsing is intended, restart the WebDAV server without the --disallow-list flag
- Access individual files directly instead of directory URLs (GET on a file is still allowed)
- Guard client code: issue PROPFIND/GET only on known file paths, or handle 403 as 'listing disabled' and skip directory traversal
Example fix
// before (client recursing directories)
for _, name := range listDir(url) { download(url + "/" + name) }
// after (handle 403 as listing disabled)
resp, _ := http.Get(dirURL)
if resp.StatusCode == http.StatusForbidden { log skip; return } Defensive patterns
Strategy: fallback
Validate before calling
// WebDAV client: skip directories when listing is disallowed
func canGet(path string, isDir bool, disallowList bool) bool {
return !isDir || !disallowList
} Type guard
func isForbidden(resp *http.Response) bool { return resp.StatusCode == http.StatusForbidden } Try / catch
resp, err := http.Get(dirURL)
if err != nil { return err }
if resp.StatusCode == http.StatusForbidden { /* listing disabled: skip */ return nil } Prevention
- Know whether the WebDAV server was started with --disallow-list
- Only generate file URLs (not directory URLs) for sharing
- Treat 403 on directories as expected behavior in recursive downloaders
When it happens
Trigger: Sending an HTTP GET to a path that resolves to a directory on the WebDAV server while the server was started with the --disallow-list option; the handler stats the path, sees info.IsDir()==true and h.DisallowList==true, and writes 'Forbidden' with status 403.
Common situations: Deployments that expose WebDAV only for direct file access (sharing individual file URLs) but disable directory listing for privacy or performance; users pasting a directory URL into a browser or running a recursive downloader against a disallow-list server.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- 400 Bad Request
- The PROPPATCH method is not currently enabled,please add the
- error creating GET request: %v
- error GET request: %v
- error GET request, status code %d
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/9a8e78513a55a21f.
Report an issue: GitHub.