valyala/fasthttp · error

cannot determine absolute path for %q: %v

Error message

cannot determine absolute path for %q: %v

What it means

During on-the-fly file compression, fasthttp computes the absolute path of the compressed cache file (original path + compressed suffix) so it can acquire a per-path file lock. filepath.Abs failed, which is rare and only happens when Getwd fails on a relative path. The opened source file is closed and the wrapped filepath error is reported with %v.

Source

Thrown at fs.go:1712

	}

	compressedFilePath := h.filePathToCompressed(filePath)

	if _, ok := h.filesystem.(*osFS); !ok {
		return h.newCompressedFSFileCache(f, fileInfo, compressedFilePath, fileEncoding)
	}

	if compressedFilePath != filePath {
		if err := os.MkdirAll(filepath.Dir(compressedFilePath), 0o750); err != nil {
			return nil, err
		}
	}
	compressedFilePath += h.compressedFileSuffixes[fileEncoding]

	absPath, err := filepath.Abs(compressedFilePath)
	if err != nil {
		_ = f.Close()
		return nil, fmt.Errorf("cannot determine absolute path for %q: %v", compressedFilePath, err)
	}

	flock := acquireFileLock(absPath)
	flock.mu.Lock()
	defer func() {
		flock.mu.Unlock()
		releaseFileLock(absPath, flock)
	}()
	return h.compressFileNolock(f, fileInfo, filePath, compressedFilePath, fileEncoding)
}

func (h *fsHandler) compressFileNolock(
	f fs.File, fileInfo fs.FileInfo, filePath, compressedFilePath, fileEncoding string,
) (*fsFile, error) {
	// Attempt to open compressed file created by another concurrent
	// goroutine.
	// It is safe opening such a file, since the file creation
	// is guarded by file mutex - see getFileLock call.

View on GitHub (pinned to c96f600972)

Solutions

  1. Use absolute paths: set FS.Root to an absolute directory or pass absolute file paths to SendFile.
  2. Ensure the process working directory exists (start the binary from a valid dir; avoid deleting the cwd).
  3. Configure FS.AbsPathToLocalPath / AbsPath so fasthttp resolves to absolute paths itself.
  4. Inspect the wrapped error: a Getwd failure like 'no such file or directory' confirms the cwd problem.

Example fix

// before
fs := &fasthttp.FS{Root: "static"}
// after
absRoot, err := filepath.Abs("static")
if err != nil { panic(err) }
fs := &fasthttp.FS{Root: absRoot}
Defensive patterns

Strategy: validation

Validate before calling

abs, err := filepath.Abs(root)
if err != nil {
    panic("working directory invalid: " + err.Error())
}
fs := &fasthttp.FS{Root: abs}

Try / catch

if strings.Contains(err.Error(), "cannot determine absolute path") {
    // restart process from a valid working directory or use absolute roots
}

Prevention

When it happens

Trigger: Calling the FS handler with a relative file path (no leading '/' and no AbsPath configured) while the process's working directory has been deleted, or in environments where os.Getwd fails (removed cwd, restricted sandbox).

Common situations: Container/sandbox where the working directory was deleted at runtime; serving files with relative paths after a chdir-based deploy wiped the original cwd; running tests that os.Chdir into temp dirs later removed.

Related errors


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