valyala/fasthttp · error

cannot open already opened file: %w

Error message

cannot open already opened file: %w

What it means

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.

Source

Thrown at fs.go:721

	}

	var r io.Reader

	ff.bigFilesLock.Lock()
	n := len(ff.bigFiles)
	if n > 0 {
		r = ff.bigFiles[n-1]
		ff.bigFiles = ff.bigFiles[:n-1]
	}
	ff.bigFilesLock.Unlock()

	if r != nil {
		return r, nil
	}

	f, err := ff.h.filesystem.Open(ff.filename)
	if err != nil {
		return nil, fmt.Errorf("cannot open already opened file: %w", err)
	}
	return &bigFileReader{
		f:  f,
		ff: ff,
		r:  f,
	}, nil
}

func (ff *fsFile) Release() {
	if ff.f != nil {
		_ = ff.f.Close()

		if ff.isBig() {
			ff.bigFilesLock.Lock()
			for _, r := range ff.bigFiles {
				_ = r.f.Close()
			}
			ff.bigFilesLock.Unlock()

View on GitHub (pinned to c96f600972)

Solutions

  1. Log the wrapped inner error (%w) to see the real cause (ENOENT vs EACCES vs EMFILE)
  2. If ENOENT: the file disappeared mid-request — re-check your deploy/rotation process or disable aggressive caching of file handles
  3. If EMFILE: raise the ulimit -n / rlimit nofile for the server process
  4. If EACCES: restore read permissions on the file and execute permission on its directories for the fasthttp process user

Example fix

// diagnose
if _, err := os.ReadFile(path); err != nil {
    log.Printf("open failed: %v", err) // reveals ENOENT/EACCES/EMFILE wrapped by this error
}
Defensive patterns

Strategy: retry

Validate before calling

if fi, err := os.Stat(path); err != nil || !fi.Mode().IsRegular() {
    return fmt.Errorf("file not servable: %s", path)
}

Type guard

func isServableFile(path string) bool {
    fi, err := os.Stat(path)
    return err == nil && fi.Mode().IsRegular()
}

Try / catch

content, err := handler(ctx)
if err != nil && strings.Contains(err.Error(), "cannot open already opened file") {
    if errors.Is(err, syscall.EMFILE) { /* raise fd limit / shed load */ }
    if errors.Is(err, fs.ErrNotExist) { /* file vanished: re-lookup or 404 */ }
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31). Data as JSON: /api/errors/55af194ebd6c567d. Report an issue: GitHub.