{"record":{"id":"3d7a5f1cf2b6b78e","repo":"caddyserver/caddy","slug":"filesystem-not-found","errorCode":null,"errorMessage":"filesystem not found","messagePattern":"filesystem not found","errorType":"http","errorClass":"caddyhttp.Error","httpStatus":404,"severity":"error","filePath":"modules/caddyhttp/fileserver/staticfiles.go","lineNumber":292,"sourceCode":"\t\tif strings.Contains(r.URL.Path, \":\") {\n\t\t\treturn caddyhttp.Error(http.StatusBadRequest, fmt.Errorf(\"illegal ADS path\"))\n\t\t}\n\t\t// reject paths with \"8.3\" short names\n\t\ttrimmedPath := strings.TrimRight(r.URL.Path, \". \") // Windows ignores trailing dots and spaces, sigh\n\t\tif len(path.Base(trimmedPath)) <= 12 && strings.Contains(trimmedPath, \"~\") {\n\t\t\treturn caddyhttp.Error(http.StatusBadRequest, fmt.Errorf(\"illegal short name\"))\n\t\t}\n\t\t// both of those could bypass file hiding or possibly leak information even if the file is not hidden\n\t}\n\n\tfilesToHide := fsrv.transformHidePaths(repl)\n\n\troot := repl.ReplaceAll(fsrv.Root, \".\")\n\tfsName := repl.ReplaceAll(fsrv.FileSystem, \"\")\n\n\tfileSystem, ok := fsrv.fsmap.Get(fsName)\n\tif !ok {\n\t\treturn caddyhttp.Error(http.StatusNotFound, fmt.Errorf(\"filesystem not found\"))\n\t}\n\n\t// remove any trailing `/` as it breaks fs.ValidPath() in the stdlib\n\tfilename := strings.TrimSuffix(caddyhttp.SanitizedPathJoin(root, r.URL.Path), \"/\")\n\n\tif c := fsrv.logger.Check(zapcore.DebugLevel, \"sanitized path join\"); c != nil {\n\t\tc.Write(\n\t\t\tzap.String(\"site_root\", root),\n\t\t\tzap.String(\"fs\", fsName),\n\t\t\tzap.String(\"request_path\", r.URL.Path),\n\t\t\tzap.String(\"result\", filename),\n\t\t)\n\t}\n\n\t// get information about the file\n\tinfo, err := fs.Stat(fileSystem, filename)\n\tif err != nil {\n\t\terr = fsrv.mapDirOpenError(fileSystem, err, filename)","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/fileserver/staticfiles.go#L274-L310","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nfile_server {\n    file_system s3bucket\n}\n# after (plugin registers the name \"s3\")\nfile_server {\n    file_system s3\n}","handlingStrategy":"validation","validationCode":"# Before deploy: every file_system name referenced must exist in the binary's module list\nfsname=$(grep -oE 'file_system\\s+\\S+' Caddyfile | awk '{print $2}' | sort -u)\nfor f in $fsname; do\n  caddy list-modules | grep -q \"caddy.fs.$f \" || { echo \"file system '$f' not registered\"; exit 1; }\ndone","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["caddy","fileserver","file-system","plugin","http-404"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}