labstack/echo · error
file does not implement io.ReadSeeker
Error message
file does not implement io.ReadSeeker
What it means
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.
Source
Thrown at context.go:695
return ErrNotFound
}
defer f.Close()
fi, _ := f.Stat()
if fi.IsDir() {
file = filepath.ToSlash(filepath.Join(file, indexPage)) // ToSlash is necessary for Windows. fs.Open and os.Open are different in that aspect.
f, err = filesystem.Open(file)
if err != nil {
return ErrNotFound
}
defer f.Close()
if fi, err = f.Stat(); err != nil {
return err
}
}
ff, ok := f.(io.ReadSeeker)
if !ok {
return errors.New("file does not implement io.ReadSeeker")
}
http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), ff)
return nil
}
// Attachment sends a response as attachment, prompting client to save the file.
//
// Avoid using the leading `/` slash as most of the Go standard library fs.FS implementations require relative paths for
// file operations.
func (c *Context) Attachment(file, name string) error {
return c.contentDisposition(file, name, "attachment")
}
// Inline sends a response as inline, opening the file in the browser.
//
// Avoid using the leading `/` slash as most of the Go standard library fs.FS implementations require relative paths for
// file operations.
func (c *Context) Inline(file, name string) error {View on GitHub (pinned to 05489dc173)
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
Example fix
// before — custom file only implements Read
type myFile struct{ r io.Reader }
func (f *myFile) Read(p []byte) (int, error) { return f.r.Read(p) }
// after — implement Seek as well
func (f *myFile) Seek(off int64, whence int) (int64, error) {
// delegate to underlying seeker or implement in-memory seek
} Defensive patterns
Strategy: type-guard
Type guard
// Verify your fs.FS returns files implementing io.ReadSeeker
func fsImplementsReadSeeker(fsys fs.FS) bool {
// best-effort: open a known file and type-assert
f, err := fsys.Open(".")
if err != nil { return true } // can't check, assume ok
defer f.Close()
_, ok := f.(io.ReadSeeker)
return ok
} Try / catch
if err := c.FileFS("path", myFS); err != nil {
if strings.Contains(err.Error(), "io.ReadSeeker") {
// fall back to reading content manually
data, _ := fs.ReadFile(myFS, "path")
return c.Blob(http.StatusOK, mime.TypeByExtension(".html"), data)
}
return err
} Prevention
- 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
When it happens
Trigger: 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").
Common situations: 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.
Related errors
- file does not implement io.ReadSeeker
- failed to unescape path variable: %w
- can not create sub FS, invalid root given, err: %w
- static middleware failed to create sub-filesystem from confi
- static middleware failed to create sub-filesystem: %w
AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04).
Data as JSON: /data/errors/348806d6a7ce1cd2.json.
Report an issue: GitHub.