{"record":{"id":"55af194ebd6c567d","repo":"valyala/fasthttp","slug":"cannot-open-already-opened-file-w","errorCode":null,"errorMessage":"cannot open already opened file: %w","messagePattern":"cannot open already opened file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"fs.go","lineNumber":721,"sourceCode":"\t}\n\n\tvar r io.Reader\n\n\tff.bigFilesLock.Lock()\n\tn := len(ff.bigFiles)\n\tif n > 0 {\n\t\tr = ff.bigFiles[n-1]\n\t\tff.bigFiles = ff.bigFiles[:n-1]\n\t}\n\tff.bigFilesLock.Unlock()\n\n\tif r != nil {\n\t\treturn r, nil\n\t}\n\n\tf, err := ff.h.filesystem.Open(ff.filename)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot open already opened file: %w\", err)\n\t}\n\treturn &bigFileReader{\n\t\tf:  f,\n\t\tff: ff,\n\t\tr:  f,\n\t}, nil\n}\n\nfunc (ff *fsFile) Release() {\n\tif ff.f != nil {\n\t\t_ = ff.f.Close()\n\n\t\tif ff.isBig() {\n\t\t\tff.bigFilesLock.Lock()\n\t\t\tfor _, r := range ff.bigFiles {\n\t\t\t\t_ = r.f.Close()\n\t\t\t}\n\t\t\tff.bigFilesLock.Unlock()","sourceCodeStart":703,"sourceCodeEnd":739,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/fs.go#L703-L739","documentation":"bigFileReader lazily (re)opens the underlying file via ff.h.filesystem.Open when a request needs the file content, wrapping any open failure. The wording means: fasthttp believed the file was already open/available but the actual OS-level open failed, so the original error is wrapped with %w.","triggerScenarios":"Serving a large file (> h.cacheSizes threshold) via FileServer/FS handler when the file is deleted, permissions change, or the path becomes unreadable between the stat/lru lookup and the actual Open call — a TOCTOU race, or a filesystem that refuses open (EACCES, EMFILE).","commonSituations":"File rotated/deleted by a deploy or log cleaner while being served; directory permissions tightened after server start; fd limits exhausted (too many open files) on busy servers.","solutions":["Log the wrapped inner error (%w) to see the real cause (ENOENT vs EACCES vs EMFILE)","If ENOENT: the file disappeared mid-request — re-check your deploy/rotation process or disable aggressive caching of file handles","If EMFILE: raise the ulimit -n / rlimit nofile for the server process","If EACCES: restore read permissions on the file and execute permission on its directories for the fasthttp process user"],"exampleFix":"// diagnose\nif _, err := os.ReadFile(path); err != nil {\n    log.Printf(\"open failed: %v\", err) // reveals ENOENT/EACCES/EMFILE wrapped by this error\n}","handlingStrategy":"retry","validationCode":"if fi, err := os.Stat(path); err != nil || !fi.Mode().IsRegular() {\n    return fmt.Errorf(\"file not servable: %s\", path)\n}","typeGuard":"func isServableFile(path string) bool {\n    fi, err := os.Stat(path)\n    return err == nil && fi.Mode().IsRegular()\n}","tryCatchPattern":"content, err := handler(ctx)\nif err != nil && strings.Contains(err.Error(), \"cannot open already opened file\") {\n    if errors.Is(err, syscall.EMFILE) { /* raise fd limit / shed load */ }\n    if errors.Is(err, fs.ErrNotExist) { /* file vanished: re-lookup or 404 */ }\n}","preventionTips":["Raise RLIMIT_NOFILE for high-traffic file servers","Keep file rotation and serving windows disjoint (rotate atomically via rename)","Run the server with a user that has read access to all served trees","Alert on this error: it usually signals a race between the OS and your deploy tooling"],"tags":["filesystem","io","fasthttp","file-server"],"backgroundTag":"file-open-failed","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}