valyala/fasthttp · error
cannot obtain info for original file %q: %w
Error message
cannot obtain info for original file %q: %w
What it means
When serving with compression enabled, fasthttp stats the original (uncompressed) file after opening the possibly-compressed one, to compare modification times and decide whether to regenerate the gzip file. This error wraps a failure of that Stat call on filePathOriginal.
Source
Thrown at fs.go:1915
if err != nil {
_ = f.Close()
return nil, fmt.Errorf("cannot obtain info for file %q: %w", filePath, err)
}
if fileInfo.IsDir() {
_ = f.Close()
if mustCompress {
return nil, fmt.Errorf("directory with unexpected suffix found: %q: suffix: %q",
filePath, h.compressedFileSuffixes[fileEncoding])
}
return nil, errDirIndexRequired
}
if mustCompress {
fileInfoOriginal, err := fs.Stat(h.filesystem, filePathOriginal)
if err != nil {
_ = f.Close()
return nil, fmt.Errorf("cannot obtain info for original file %q: %w", filePathOriginal, err)
}
// Only re-create the compressed file if there was more than a second between the mod times.
// On macOS the gzip seems to truncate the nanoseconds in the mod time causing the original file
// to look newer than the gzipped file.
if fileInfoOriginal.ModTime().Sub(fileInfo.ModTime()) >= time.Second {
// The compressed file became stale. Re-create it.
_ = f.Close()
_ = os.Remove(filePath)
return h.compressAndOpenFSFile(filePathOriginal, fileEncoding)
}
}
return h.newFSFile(f, fileInfo, mustCompress, filePath, fileEncoding)
}
func (h *fsHandler) newFSFile(f fs.File, fileInfo fs.FileInfo, compressed bool, filePath, fileEncoding string) (*fsFile, error) {
n := fileInfo.Size()View on GitHub (pinned to c96f600972)
Solutions
- Keep the original uncompressed file alongside the .gz/.br file
- Verify the original file path exists and is accessible
- Fix symlinks or deploy scripts that remove originals
- Disable Compress in the FS config if only pre-compressed files are deployed
Example fix
// before $ rm dist/app.js # keep only dist/app.js.gz // after $ gzip -k dist/app.js # keep both dist/app.js and dist/app.js.gz
Defensive patterns
Strategy: validation
Validate before calling
for _, p := range []string{orig, orig + ".gz"} { if _, err := os.Stat(p); err != nil { return err } } Try / catch
if err := ctx.SendFile(path); err != nil { log.Printf("compress-served file error: %v", err); ctx.Error("internal", 500) } Prevention
- Deploy originals together with compressed variants (gzip -k)
- Check deploy scripts do not delete uncompressed sources
- Verify symlinks resolve on the server
When it happens
Trigger: Using an FS handler with Compress enabled where the original file (path without the compressed suffix) cannot be stat'd: it was deleted, renamed, or the path is invalid on the custom filesystem.
Common situations: Pre-compressed workflow where the .gz file is kept but the original was removed; symlinks pointing to non-existent originals; race during asset redeployment.
Related errors
- cannot create temporary file for %q: %w
- error when compressing file %q to %q: %w
- cannot change modification time to %v for tmp file %q: %v
- cannot move compressed file from %q to %q: %w
- directory with unexpected suffix found: %q: suffix: %q
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/fd3e03aa8e3ab258.
Report an issue: GitHub.