valyala/fasthttp · error
cannot read header of the file %q: %w
Error message
cannot read header of the file %q: %w
What it means
When building the *fsFile for a (possibly compressed) file, fasthttp needs a Content-Type. If mime.TypeByExtension can't determine it from the extension, it reads the first bytes of the file (readFileHeader, decompressing if needed) to sniff the type via http.DetectContentType. If that header read fails, this error wraps the cause with the file's base name. The file cannot be served without a content type path succeeding.
Source
Thrown at fs.go:1842
if err != nil {
return nil, fmt.Errorf("error when compressing file %q: %w", filePath, err)
}
seeker, ok := f.(io.Seeker)
if !ok {
return nil, errors.New("seek is not implemented")
}
if _, err = seeker.Seek(0, io.SeekStart); err != nil {
return nil, err
}
ext := fileExtension(fileInfo.Name(), false, h.compressedFileSuffixes[fileEncoding])
contentType := mime.TypeByExtension(ext)
if contentType == "" {
data, err := readFileHeader(f, false, fileEncoding)
if err != nil {
return nil, fmt.Errorf("cannot read header of the file %q: %w", fileInfo.Name(), err)
}
contentType = http.DetectContentType(data)
}
dirIndex := w.B
lastModified := fileInfo.ModTime()
ff := &fsFile{
h: h,
dirIndex: dirIndex,
contentType: contentType,
contentLength: len(dirIndex),
compressed: true,
lastModified: lastModified,
lastModifiedStr: AppendHTTPDate(nil, lastModified),
t: time.Now(),
}
View on GitHub (pinned to c96f600972)
Solutions
- Check the wrapped cause; if reading the compressed cache failed, delete the stale compressed cache files (suffix .fasthttp.*) and let them regenerate.
- Ensure served files are fully written (atomic uploads: write temp + rename).
- Add the file's extension mapping via mime.AddExtensionType so sniffing isn't needed.
- Verify the file is non-empty and readable by the server user.
Example fix
// before: extensionless, truncated file causes sniff failure
// after: register MIME and ensure atomic writes
mime.AddExtensionType("", "application/octet-stream")
// upload pattern:
// os.WriteFile(f+".tmp", data, 0o644); os.Rename(f+".tmp", f) Defensive patterns
Strategy: validation
Validate before calling
mime.AddExtensionType("", "application/octet-stream")
if fi, err := os.Stat(path); err != nil || fi.Size() == 0 {
// reject empty/missing files before serving
} Try / catch
if strings.Contains(err.Error(), "cannot read header of the file") {
// delete stale *.fasthttp.* cache and serve 500/404; files will regenerate
} Prevention
- Register MIME types for all served extensions (mime.AddExtensionType).
- Write files atomically (temp + rename) so sniffing never sees truncated data.
- Purge corrupt compressed cache files after crashes or partial deploys.
When it happens
Trigger: Requesting a file whose extension is unknown to mime.TypeByExtension AND whose content cannot be read/decompressed for sniffing — e.g. corrupted compressed cache file, read error mid-header, or a file that shrank to 0 bytes after Stat.
Common situations: Serving files without extensions that were truncated or corrupted; a stale/corrupt fasthttp compressed cache file (e.g. .fasthttp.gz) truncated by a crash; deploying partially uploaded files.
Related errors
- fasthttp: request content-type has bad boundary or is not mu
- fasthttp: no args value for the given key
- fasthttp: pipelined requests' queue has been overflowed. inc
- pipeline connection has been stopped
- fasthttp: no cookies found
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/c22524bfe6bebffb.
Report an issue: GitHub.