valyala/fasthttp · error

error when compressing file %q to %q: %w

Error message

error when compressing file %q to %q: %w

What it means

This error occurs inside fasthttp's file compression routine when the actual compression step (gzip/brotli/zstd writer writing the temp file) returns an error. The library closes the temp and source files, removes the partial temp file, and wraps the compression error with the source path and temp path. It indicates the compressed output could not be produced, not a filesystem permission problem.

Source

Thrown at fs.go:1779

		zw := acquireStacklessGzipWriter(zf, CompressDefaultCompression)
		_, err = copyZeroAlloc(zw, f)
		if errf := zw.Flush(); err == nil {
			err = errf
		}
		releaseStacklessGzipWriter(zw, CompressDefaultCompression)
	case "zstd":
		zw := acquireStacklessZstdWriter(zf, CompressZstdDefault)
		_, err = copyZeroAlloc(zw, f)
		if errf := zw.Flush(); err == nil {
			err = errf
		}
		releaseStacklessZstdWriter(zw, CompressZstdDefault)
	}
	_ = zf.Close()
	_ = f.Close()
	if err != nil {
		_ = os.Remove(tmpFilePath)
		return nil, fmt.Errorf("error when compressing file %q to %q: %w", filePath, tmpFilePath, err)
	}
	if err = os.Chtimes(tmpFilePath, time.Now(), fileInfo.ModTime()); err != nil {
		_ = os.Remove(tmpFilePath)
		return nil, fmt.Errorf("cannot change modification time to %v for tmp file %q: %v",
			fileInfo.ModTime(), tmpFilePath, err)
	}
	if err = os.Rename(tmpFilePath, compressedFilePath); err != nil {
		_ = os.Remove(tmpFilePath)
		return nil, fmt.Errorf("cannot move compressed file from %q to %q: %w", tmpFilePath, compressedFilePath, err)
	}
	return h.newCompressedFSFile(compressedFilePath, fileEncoding)
}

// newCompressedFSFileCache use memory cache compressed files.
func (h *fsHandler) newCompressedFSFileCache(f fs.File, fileInfo fs.FileInfo, filePath, fileEncoding string) (*fsFile, error) {
	var (
		w   = &bytebufferpool.ByteBuffer{}
		err error

View on GitHub (pinned to c96f600972)

Solutions

  1. Check the wrapped cause: ENOSPC means free disk space in the directory holding compressed cache files.
  2. Pre-generate compressed assets at deploy time (e.g. gzip -k) so the server only serves existing cache files.
  3. Retry the request: the failed temp file is removed, and a subsequent request retries compression.
  4. Ensure the cache filesystem is healthy and writable (avoid unreliable network mounts for cache).

Example fix

// before: letting server compress at first request on a full disk
fs := &fasthttp.FS{Root: "/srv/assets", Compress: true}
// after: precompress at build/deploy
// find /srv/assets -type f -exec gzip -9k {} \;
fs := &fasthttp.FS{Root: "/srv/assets", Compress: true, CompressedFileSuffix: ".gz"}
Defensive patterns

Strategy: retry

Validate before calling

// pre-generate compressed assets so runtime compression is skipped:
// exec.Command("gzip", "-9k", path).Run()

Try / catch

if strings.Contains(err.Error(), "error when compressing file") {
    // temp file already removed; retry once, then serve uncompressed
    ctx.SetStatusCode(fasthttp.StatusOK) // fall back path
}

Prevention

When it happens

Trigger: Compressing a very large file with a zstd/gzip/brotli writer that hits an I/O error writing to the temp file (disk full mid-write), or a writer-level failure while generating the compressed cache file during the first request for that file+encoding.

Common situations: Disk filling up while the first request triggers compression; serving from flaky network storage where writes to the temp file fail; memory pressure killing/resetting compressor state in embedded environments.

Related errors


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