{"record":{"id":"fd3e03aa8e3ab258","repo":"valyala/fasthttp","slug":"cannot-obtain-info-for-original-file-q-w","errorCode":null,"errorMessage":"cannot obtain info for original file %q: %w","messagePattern":"cannot obtain info for original file %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"fs.go","lineNumber":1915,"sourceCode":"\tif err != nil {\n\t\t_ = f.Close()\n\t\treturn nil, fmt.Errorf(\"cannot obtain info for file %q: %w\", filePath, err)\n\t}\n\n\tif fileInfo.IsDir() {\n\t\t_ = f.Close()\n\t\tif mustCompress {\n\t\t\treturn nil, fmt.Errorf(\"directory with unexpected suffix found: %q: suffix: %q\",\n\t\t\t\tfilePath, h.compressedFileSuffixes[fileEncoding])\n\t\t}\n\t\treturn nil, errDirIndexRequired\n\t}\n\n\tif mustCompress {\n\t\tfileInfoOriginal, err := fs.Stat(h.filesystem, filePathOriginal)\n\t\tif err != nil {\n\t\t\t_ = f.Close()\n\t\t\treturn nil, fmt.Errorf(\"cannot obtain info for original file %q: %w\", filePathOriginal, err)\n\t\t}\n\n\t\t// Only re-create the compressed file if there was more than a second between the mod times.\n\t\t// On macOS the gzip seems to truncate the nanoseconds in the mod time causing the original file\n\t\t// to look newer than the gzipped file.\n\t\tif fileInfoOriginal.ModTime().Sub(fileInfo.ModTime()) >= time.Second {\n\t\t\t// The compressed file became stale. Re-create it.\n\t\t\t_ = f.Close()\n\t\t\t_ = os.Remove(filePath)\n\t\t\treturn h.compressAndOpenFSFile(filePathOriginal, fileEncoding)\n\t\t}\n\t}\n\n\treturn h.newFSFile(f, fileInfo, mustCompress, filePath, fileEncoding)\n}\n\nfunc (h *fsHandler) newFSFile(f fs.File, fileInfo fs.FileInfo, compressed bool, filePath, fileEncoding string) (*fsFile, error) {\n\tn := fileInfo.Size()","sourceCodeStart":1897,"sourceCodeEnd":1933,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/fs.go#L1897-L1933","documentation":"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.","triggerScenarios":"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.","commonSituations":"Pre-compressed workflow where the .gz file is kept but the original was removed; symlinks pointing to non-existent originals; race during asset redeployment.","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"],"exampleFix":"// before\n$ rm dist/app.js      # keep only dist/app.js.gz\n// after\n$ gzip -k dist/app.js # keep both dist/app.js and dist/app.js.gz","handlingStrategy":"validation","validationCode":"for _, p := range []string{orig, orig + \".gz\"} { if _, err := os.Stat(p); err != nil { return err } }","typeGuard":null,"tryCatchPattern":"if err := ctx.SendFile(path); err != nil { log.Printf(\"compress-served file error: %v\", err); ctx.Error(\"internal\", 500) }","preventionTips":["Deploy originals together with compressed variants (gzip -k)","Check deploy scripts do not delete uncompressed sources","Verify symlinks resolve on the server"],"tags":["filesystem","fasthttp","compression"],"backgroundTag":"file-stat-failed","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}