{"id":"e5a47b8045c7da6f","repo":"labstack/echo","slug":"file-does-not-implement-io-readseeker-e5a47b","errorCode":null,"errorMessage":"file does not implement io.ReadSeeker","messagePattern":"file does not implement io\\.ReadSeeker","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/static.go","lineNumber":319,"sourceCode":"\t\t\t\tdefer index.Close()\n\n\t\t\t\tinfo, err = index.Stat()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\n\t\t\t\treturn serveFile(c, index, info)\n\t\t\t}\n\n\t\t\treturn serveFile(c, file, info)\n\t\t}\n\t}, nil\n}\n\nfunc serveFile(c *echo.Context, file fs.File, info os.FileInfo) error {\n\tff, ok := file.(io.ReadSeeker)\n\tif !ok {\n\t\treturn errors.New(\"file does not implement io.ReadSeeker\")\n\t}\n\thttp.ServeContent(c.Response(), c.Request(), info.Name(), info.ModTime(), ff)\n\treturn nil\n}\n\nfunc listDir(t *template.Template, pathInFs string, filesystem fs.FS, res http.ResponseWriter) error {\n\tfiles, err := fs.ReadDir(filesystem, pathInFs)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"static middleware failed to read directory for listing: %w\", err)\n\t}\n\n\t// Create directory index\n\tres.Header().Set(echo.HeaderContentType, echo.MIMETextHTMLCharsetUTF8)\n\tdata := struct {\n\t\tName  string\n\t\tFiles []any\n\t}{\n\t\tName: pathInFs,","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/middleware/static.go#L301-L337","documentation":"Returned at request time by serveFile in the Static middleware when the opened fs.File does not satisfy io.ReadSeeker. http.ServeContent needs to Seek (to support Range requests and determine Content-Length), so a file that only implements Read cannot be served. The standard os.File and embed.FS files implement ReadSeeker; custom fs.FS implementations (e.g., streaming or generated readers) may not.","triggerScenarios":"Configuring StaticConfig with a custom fs.FS whose Open returns a file lacking a Seek method; or wrapping the default filesystem with a decorator that hides Seek. The error is returned from the handler during a request that resolves to a file.","commonSituations":"Using a custom filesystem backed by object storage / a streaming reader / a generated asset source where files are not seekable; or an fs.FS adapter that returns a wrapper type without forwarding Seek.","solutions":["Ensure your custom fs.File implementation also implements Seek(offset, whence) (int64, error) so it satisfies io.ReadSeeker.","If the source truly cannot seek, pre-buffer the content into a bytes.Reader (which implements ReadSeeker) before returning from Open.","Use embed.FS or the default os-based filesystem, whose files already implement ReadSeeker.","If you cannot change the filesystem, serve the content yourself with c.Stream / c.Blob instead of the Static middleware."],"exampleFix":"// before: custom file only implements Read\ntype streamFile struct{ *bytes.Reader }\n// after: embed a *bytes.Reader so Read+Seek are satisfied\ntype seekableFile struct{ *bytes.Reader }\nfunc (f *seekableFile) Stat() (fs.FileInfo, error) { return fstat, nil }\nfunc (f *seekableFile) Close() error { return nil }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func canServeContent(f fs.File) bool {\n    _, ok := f.(io.ReadSeeker)\n    return ok\n}\n\n// usage before http.ServeContent:\n// if !canServeContent(file) { return echo.NewHTTPError(http.StatusInternalServerError, \"file not seekable\") }","tryCatchPattern":null,"preventionTips":["Ensure custom fs.File implementations implement both Read and Seek (i.e., io.ReadSeeker).","If the source is not seekable, buffer content into a *bytes.Reader before returning from Open.","Prefer embed.FS or the default os filesystem, whose files already satisfy ReadSeeker.","If you cannot make the file seekable, serve it yourself with c.Stream instead of the Static middleware."],"tags":["middleware","static","filesystem","runtime","io"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}