{"id":"3b3f1cff0238c578","repo":"labstack/echo","slug":"static-middleware-failed-to-create-sub-filesystem","errorCode":null,"errorMessage":"static middleware failed to create sub-filesystem from config.Root, error: %w","messagePattern":"static middleware failed to create sub-filesystem from config\\.Root, error: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/static.go","lineNumber":208,"sourceCode":"\t}\n\tif config.DirectoryListTemplate == \"\" {\n\t\tconfig.DirectoryListTemplate = directoryListHTMLTemplate\n\t}\n\n\tdirListTemplate, tErr := template.New(\"index\").Parse(config.DirectoryListTemplate)\n\tif tErr != nil {\n\t\treturn nil, fmt.Errorf(\"echo static middleware directory list template parsing error: %w\", tErr)\n\t}\n\n\tvar once *sync.Once\n\tvar fsErr error\n\tcurrentFS := config.Filesystem\n\tif config.Filesystem == nil {\n\t\tonce = &sync.Once{}\n\t} else if config.Root != \".\" {\n\t\ttmpFs, fErr := fs.Sub(config.Filesystem, path.Join(\".\", config.Root))\n\t\tif fErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"static middleware failed to create sub-filesystem from config.Root, error: %w\", fErr)\n\t\t}\n\t\tcurrentFS = tmpFs\n\t}\n\n\treturn func(next echo.HandlerFunc) echo.HandlerFunc {\n\t\treturn func(c *echo.Context) (err error) {\n\t\t\tif config.Skipper(c) {\n\t\t\t\treturn next(c)\n\t\t\t}\n\n\t\t\tp := c.Request().URL.Path\n\t\t\tif strings.HasSuffix(c.Path(), \"*\") { // When serving from a group, e.g. `/static*`.\n\t\t\t\tp = c.Param(\"*\")\n\t\t\t}\n\t\t\tif config.EnablePathUnescaping {\n\t\t\t\tp, err = url.PathUnescape(p)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/middleware/static.go#L190-L226","documentation":"Returned by StaticConfig.ToMiddleware() (eager path, static.go:208) when fs.Sub(config.Filesystem, config.Root) fails while a custom Filesystem AND a non-'.' Root are both set. fs.Sub can fail if the root path is invalid for the filesystem implementation. This is detected at middleware construction time.","triggerScenarios":"Providing StaticConfig.Filesystem (e.g. an embed.FS) together with a Root that does not exist within that filesystem, or a Root containing characters the FS rejects. For example Root='assets' when the embed.FS only contains 'static/'.","commonSituations":"Embedding files with '//go:embed static' but setting Root='assets'; using a custom fs.FS whose Sub implementation returns an error for the given path; mismatch between the directory embedded and the Root configured.","solutions":["Ensure config.Root matches a real directory inside the provided Filesystem (check embed directives vs Root).","Use echo.MustSubFS(filesystem, root) which panics loudly during setup instead of failing per-request, or fs.Sub manually first to test.","Set Root to '.' when your Filesystem is already scoped to the target directory.","Double-check the embed path: '//go:embed static/*' embeds under 'static/', so Root should be 'static'."],"exampleFix":"// before\n//go:embed assets/*\nvar embedded embed.FS\ncfg := middleware.StaticConfig{Filesystem: embedded, Root: \"static\"} // wrong: embedded under 'assets'\n// after\ncfg := middleware.StaticConfig{Filesystem: embedded, Root: \"assets\"}\n// or scope it first:\nsub, _ := fs.Sub(embedded, \"assets\")\ncfg := middleware.StaticConfig{Filesystem: sub, Root: \".\"}","handlingStrategy":"validation","validationCode":"// Confirm the Root exists inside the filesystem before configuring Static.\nfunc subExists(fsys fs.FS, root string) error {\n    sub, err := fs.Sub(fsys, root)\n    if err != nil { return err }\n    entries, err := fs.ReadDir(sub, \".\")\n    if err != nil { return err }\n    _ = entries\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build the sub-filesystem once with echo.MustSubFS at setup time so errors surface immediately.","Keep embed directives and Root values in sync; verify after every embed path change.","Use Root='.' when the Filesystem is already scoped to the target dir."],"tags":["config","static","filesystem","embed","startup"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}