gofiber/fiber · error
stat %q: %w
Error message
stat %q: %w
What it means
Returned by sendFileContentLength() when cfg.FS is set (embed.FS, os.DirFS, etc.) and fs.Stat fails on the cleaned path. This stat is only invoked for byte-range requests to compute Content-Length / handle 416 responses. The wrapped %w is the fs.FS error (typically fs.ErrNotExist or fs.ErrPermission).
Source
Thrown at res.go:1175
if cacheControlValue != "" {
response.Header.Set(HeaderCacheControl, cacheControlValue)
}
return nil
}
return nil
}
func sendFileContentLength(path string, cfg SendFile) (int64, error) {
if cfg.FS != nil {
cleanPath := pathpkg.Clean(utils.TrimLeft(path, '/'))
if cleanPath == "." {
cleanPath = ""
}
info, err := fs.Stat(cfg.FS, cleanPath)
if err != nil {
return 0, fmt.Errorf("stat %q: %w", cleanPath, err)
}
return info.Size(), nil
}
info, err := os.Stat(filepath.FromSlash(path))
if err != nil {
return 0, fmt.Errorf("stat %q: %w", path, err)
}
return info.Size(), nil
}
// SendStatus sets the HTTP status code and if the response body is empty,
// it sets the correct status message in the body.
func (r *DefaultRes) SendStatus(status int) error {
r.Status(status)
if statusDisallowsBody(status) {View on GitHub (pinned to a105acad6c)
Solutions
- Verify the file exists inside the fs.FS by listing it at startup (fs.Stat(cfg.FS, path)) for the known asset set.
- Widen the //go:embed directive to include all assets served via byte-range.
- Confirm SendFile.FS is the same FS the routes were configured against.
- If the error is intermittent, guard against concurrent deletion or regenerate the embed cache.
Example fix
// before — embed pattern misses subdir //go:embed assets/*.png var assets embed.FS // request for assets/icons/star.png -> stat "assets/icons/star.png": file does not exist // after //go:embed assets/**/*.png var assets embed.FS
Defensive patterns
Strategy: validation
Validate before calling
// At startup, verify every byte-range-served file exists in the FS.
func verifyFS(fsroot fs.FS, files []string) error {
for _, f := range files {
if _, err := fs.Stat(fsroot, f); err != nil {
return fmt.Errorf("%s: %w", f, err)
}
}
return nil
} Try / catch
if err := c.Res().SendFile(path, fiber.SendFile{FS: assets, ByteRange: true}); err != nil {
if strings.Contains(err.Error(), "stat") {
return fiber.NewError(fiber.StatusNotFound, "asset not found")
}
return err
} Prevention
- Widen //go:embed patterns to cover all served assets.
- Run fs.WalkDir at startup to log the embedded file set.
- Disable ByteRange on routes whose files are volatile.
When it happens
Trigger: A request with a Range header arrives, SendFile.ByteRange is true, cfg.FS is set, and the file referenced is missing inside the FS, or the FS denies access (permission bit on an embed subtree, or a path that escapes the FS root after cleaning).
Common situations: Embed.FS does not include the requested file (//go:embed pattern too narrow); a Range request for a file removed between route registration and request; SendFile.ByteRange enabled but the FS root was mounted incorrectly; path traversal sanitized to empty after Clean.
Related errors
- failed to determine abs file path: %w
- fiber: failed to reload views: %w
- open file error: %w
- failed to check directory: %w
- failed to create directory: %w
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/e4ecc8378693aa26.
Report an issue: GitHub.