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

  1. Verify the name matches exactly (case-sensitive) the file system registered by your fs plugin.
  2. Ensure the plugin is in the build: `caddy list-modules | grep fs.` and rebuild with xcaddy if missing.
  3. If the name comes from a placeholder, log/check its expanded value (the request logs show fs=...) and fix the environment variable or default.
  4. 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

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


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