{"id":"348806d6a7ce1cd2","repo":"labstack/echo","slug":"file-does-not-implement-io-readseeker","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":"context.go","lineNumber":695,"sourceCode":"\t\treturn ErrNotFound\n\t}\n\tdefer f.Close()\n\n\tfi, _ := f.Stat()\n\tif fi.IsDir() {\n\t\tfile = filepath.ToSlash(filepath.Join(file, indexPage)) // ToSlash is necessary for Windows. fs.Open and os.Open are different in that aspect.\n\t\tf, err = filesystem.Open(file)\n\t\tif err != nil {\n\t\t\treturn ErrNotFound\n\t\t}\n\t\tdefer f.Close()\n\t\tif fi, err = f.Stat(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tff, ok := f.(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(), fi.Name(), fi.ModTime(), ff)\n\treturn nil\n}\n\n// Attachment sends a response as attachment, prompting client to save the file.\n//\n// Avoid using the leading `/` slash as most of the Go standard library fs.FS implementations require relative paths for\n// file operations.\nfunc (c *Context) Attachment(file, name string) error {\n\treturn c.contentDisposition(file, name, \"attachment\")\n}\n\n// Inline sends a response as inline, opening the file in the browser.\n//\n// Avoid using the leading `/` slash as most of the Go standard library fs.FS implementations require relative paths for\n// file operations.\nfunc (c *Context) Inline(file, name string) error {","sourceCodeStart":677,"sourceCodeEnd":713,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/context.go#L677-L713","documentation":"Returned by fsFile (used by Context.File, FileFS, Inline, Attachment) when the file opened from the configured fs.FS does not implement io.ReadSeeker. http.ServeContent requires a ReadSeeker to set Content-Length, handle Range requests, and stream efficiently; a reader that only implements Read cannot be served this way. Standard os.File and embed.FS files implement ReadSeeker, but custom fs.FS implementations may not.","triggerScenarios":"Providing a custom fs.FS whose Open returns an io.Reader that does not also implement Seek (io.ReadSeeker), then calling c.FileFS(\"path\", myFS) or setting Echo.Filesystem and calling c.File(\"path\").","commonSituations":"Custom virtual filesystem reading from a network source, compressed archive, or stream. Wrapping an io.Reader in a struct that only exposes Read. Testing with a mock FS that returns a bytes.Reader incorrectly wrapped.","solutions":["Ensure your fs.FS file objects implement both Read and Seek (i.e. io.ReadSeeker); wrap a bytes.Reader or use os.File","If the data is fully in memory, open into a bytes.Reader which implements io.ReadSeeker","If seeking is impossible, read the content yourself and send it via c.Blob or c.Stream instead of c.File/FileFS"],"exampleFix":"// before — custom file only implements Read\ntype myFile struct{ r io.Reader }\nfunc (f *myFile) Read(p []byte) (int, error) { return f.r.Read(p) }\n\n// after — implement Seek as well\nfunc (f *myFile) Seek(off int64, whence int) (int64, error) {\n    // delegate to underlying seeker or implement in-memory seek\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Verify your fs.FS returns files implementing io.ReadSeeker\nfunc fsImplementsReadSeeker(fsys fs.FS) bool {\n    // best-effort: open a known file and type-assert\n    f, err := fsys.Open(\".\")\n    if err != nil { return true } // can't check, assume ok\n    defer f.Close()\n    _, ok := f.(io.ReadSeeker)\n    return ok\n}","tryCatchPattern":"if err := c.FileFS(\"path\", myFS); err != nil {\n    if strings.Contains(err.Error(), \"io.ReadSeeker\") {\n        // fall back to reading content manually\n        data, _ := fs.ReadFile(myFS, \"path\")\n        return c.Blob(http.StatusOK, mime.TypeByExtension(\".html\"), data)\n    }\n    return err\n}","preventionTips":["Ensure custom fs.FS file objects implement both Read and Seek","Use bytes.Reader (which implements ReadSeeker) for in-memory data","For non-seekable streams, read fully and serve via c.Blob or c.Stream instead of c.File"],"tags":["filesystem","static-files","io-readseeker","serve-content"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}