{"record":{"id":"4d7d8542cdf8f46d","repo":"valyala/fasthttp","slug":"cannot-change-modification-time-to-v-for-tmp-file","errorCode":null,"errorMessage":"cannot change modification time to %v for tmp file %q: %v","messagePattern":"cannot change modification time to (.+?) for tmp file %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"fs.go","lineNumber":1783,"sourceCode":"\t\t}\n\t\treleaseStacklessGzipWriter(zw, CompressDefaultCompression)\n\tcase \"zstd\":\n\t\tzw := acquireStacklessZstdWriter(zf, CompressZstdDefault)\n\t\t_, err = copyZeroAlloc(zw, f)\n\t\tif errf := zw.Flush(); err == nil {\n\t\t\terr = errf\n\t\t}\n\t\treleaseStacklessZstdWriter(zw, CompressZstdDefault)\n\t}\n\t_ = zf.Close()\n\t_ = f.Close()\n\tif err != nil {\n\t\t_ = os.Remove(tmpFilePath)\n\t\treturn nil, fmt.Errorf(\"error when compressing file %q to %q: %w\", filePath, tmpFilePath, err)\n\t}\n\tif err = os.Chtimes(tmpFilePath, time.Now(), fileInfo.ModTime()); err != nil {\n\t\t_ = os.Remove(tmpFilePath)\n\t\treturn nil, fmt.Errorf(\"cannot change modification time to %v for tmp file %q: %v\",\n\t\t\tfileInfo.ModTime(), tmpFilePath, err)\n\t}\n\tif err = os.Rename(tmpFilePath, compressedFilePath); err != nil {\n\t\t_ = os.Remove(tmpFilePath)\n\t\treturn nil, fmt.Errorf(\"cannot move compressed file from %q to %q: %w\", tmpFilePath, compressedFilePath, err)\n\t}\n\treturn h.newCompressedFSFile(compressedFilePath, fileEncoding)\n}\n\n// newCompressedFSFileCache use memory cache compressed files.\nfunc (h *fsHandler) newCompressedFSFileCache(f fs.File, fileInfo fs.FileInfo, filePath, fileEncoding string) (*fsFile, error) {\n\tvar (\n\t\tw   = &bytebufferpool.ByteBuffer{}\n\t\terr error\n\t)\n\n\tswitch fileEncoding {\n\tcase \"br\":","sourceCodeStart":1765,"sourceCodeEnd":1801,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/fs.go#L1765-L1801","documentation":"After compressing into a temp file, fasthttp calls os.Chtimes to set the temp file's modification time to the original file's modtime so HTTP caching (Last-Modified/ETag) stays consistent. If Chtimes fails, the temp file is removed and this error is returned with the intended modtime and temp path. This usually means the temp file vanished or the filesystem disallows timestamp changes.","triggerScenarios":"os.Chtimes failing on the just-created temp file during on-demand compression — typically because the temp file was deleted concurrently (external cleaner), the filesystem does not support utimes (some network/FUSE mounts), or an OS-level error (EINVAL on exotic fs).","commonSituations":"tmpwatch/systemd-tmpfiles cleaners racing with compression in cache dirs; FUSE/NFS mounts lacking utimes support; containers with restricted syscalls (seccomp blocking utimensat).","solutions":["Exclude fasthttp's compressed-file cache directory from external cleanup daemons (tmpwatch, systemd-tmpfiles).","Check the wrapped cause; if it's 'operation not supported', move cache files to a local filesystem (ext4/tmpfs).","Retry the request: the failed temp file is removed and the next attempt recompresses.","If seccomp/apparmor blocks utimensat, adjust the container security profile."],"exampleFix":"// before: cleaner racing with cache\n// systemd-tmpfiles rule purging the whole webroot hourly\n// after: exclude *.fasthttp.gz / cache dir from cleanup, or use local cache dir\nfs := &fasthttp.FS{Root: \"/mnt/net-assets\", Compress: true} // move CachePath to local disk:\nfs.CachePath = \"/var/cache/app/fs\"","handlingStrategy":"retry","validationCode":"// ensure the cache filesystem supports utimes before enabling compression:\nif err := os.Chtimes(testFile, time.Now(), time.Now()); err != nil {\n    // disable compression or relocate cache to local fs\n}","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"cannot change modification time\") {\n    // transient; safe to retry the request, temp file was cleaned up\n}","preventionTips":["Exclude fasthttp cache files from tmpwatch/systemd-tmpfiles cleanup.","Place compressed cache on a local filesystem (ext4/tmpfs), not FUSE/NFS.","Check container seccomp/AppArmor allows utimensat."],"tags":["filesystem","fasthttp","compression","file-timestamps"],"backgroundTag":"chtimes-failed","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}