caddyserver/caddy · error · caddyhttp.Error
filesystem not found
Error message
filesystem not found
What it means
Returned by FileServer.ServeHTTP when the configured file system name (the `file_system` setting, after placeholder replacement) is not found in the server's file system map. This feature lets file_server serve from non-disk backends; an unknown name yields HTTP 404 with this message at request time.
Source
Thrown at modules/caddyhttp/fileserver/staticfiles.go:292
if strings.Contains(r.URL.Path, ":") {
return caddyhttp.Error(http.StatusBadRequest, fmt.Errorf("illegal ADS path"))
}
// reject paths with "8.3" short names
trimmedPath := strings.TrimRight(r.URL.Path, ". ") // Windows ignores trailing dots and spaces, sigh
if len(path.Base(trimmedPath)) <= 12 && strings.Contains(trimmedPath, "~") {
return caddyhttp.Error(http.StatusBadRequest, fmt.Errorf("illegal short name"))
}
// both of those could bypass file hiding or possibly leak information even if the file is not hidden
}
filesToHide := fsrv.transformHidePaths(repl)
root := repl.ReplaceAll(fsrv.Root, ".")
fsName := repl.ReplaceAll(fsrv.FileSystem, "")
fileSystem, ok := fsrv.fsmap.Get(fsName)
if !ok {
return caddyhttp.Error(http.StatusNotFound, fmt.Errorf("filesystem not found"))
}
// remove any trailing `/` as it breaks fs.ValidPath() in the stdlib
filename := strings.TrimSuffix(caddyhttp.SanitizedPathJoin(root, r.URL.Path), "/")
if c := fsrv.logger.Check(zapcore.DebugLevel, "sanitized path join"); c != nil {
c.Write(
zap.String("site_root", root),
zap.String("fs", fsName),
zap.String("request_path", r.URL.Path),
zap.String("result", filename),
)
}
// get information about the file
info, err := fs.Stat(fileSystem, filename)
if err != nil {
err = fsrv.mapDirOpenError(fileSystem, err, filename)View on GitHub (pinned to 50e54ee279)
Solutions
- Verify the name matches exactly (case-sensitive) the file system registered by your fs plugin.
- Ensure the plugin is in the build: `caddy list-modules | grep fs.` and rebuild with xcaddy if missing.
- If the name comes from a placeholder, log/check its expanded value (the request logs show fs=...) and fix the environment variable or default.
- Remove `file_system` to use the default OS filesystem if that was the intent.
Example fix
# before
file_server {
file_system s3bucket
}
# after (plugin registers the name "s3")
file_server {
file_system s3
} Defensive patterns
Strategy: validation
Validate before calling
# Before deploy: every file_system name referenced must exist in the binary's module list
fsname=$(grep -oE 'file_system\s+\S+' Caddyfile | awk '{print $2}' | sort -u)
for f in $fsname; do
caddy list-modules | grep -q "caddy.fs.$f " || { echo "file system '$f' not registered"; exit 1; }
done Prevention
- Cross-check file_system names against `caddy list-modules` output in CI.
- Keep fs plugin builds pinned via xcaddy and documented per environment.
- If the name is placeholder-driven, assert the placeholder resolves (log fs= per request) before rollout.
When it happens
Trigger: Setting `file_system mycustom` on a file_server (or handler config) where no module registered a file system named 'mycustom' — e.g. the plugin providing it is not compiled in, the name is misspelled, or a placeholder like {env.FS_NAME} expands to an empty/unknown value.
Common situations: Using caddy-fs plugins (e.g. S3/embedded file systems) and forgetting the plugin in the xcaddy build; typos between the file_system definition site and the file_server usage; placeholder-driven names that resolve differently at runtime.
Related errors
- module %s is not a precompressor; is %T
- [%s] key does not exist: %s
- adding encoding %s: %v
- encoder does not specify an Accept-Encoding value
- encoder already added: %s
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/3d7a5f1cf2b6b78e.
Report an issue: GitHub.