valyala/fasthttp · warning
cannot access directory without index page: directory %q
Error message
cannot access directory without index page: directory %q
What it means
The FS handler was asked to serve a directory whose index file could not be resolved, and index page generation is disabled (Config.GenerateIndexPages == false). fasthttp therefore cannot produce any representation of the directory and returns this error, which typically surfaces to the client as 403/500.
Source
Thrown at fs.go:1557
}
ff, err := h.openFSFile(indexFilePath, mustCompress, fileEncoding)
if err == nil {
return ff, nil
}
if mustCompress && err == errNoCreatePermission {
ctx.Logger().Printf("insufficient permissions for saving compressed file for %q. Serving uncompressed file. "+
"Allow write access to the directory with this file in order to improve fasthttp performance", indexFilePath)
mustCompress = false
return h.openFSFile(indexFilePath, mustCompress, fileEncoding)
}
if !errors.Is(err, fs.ErrNotExist) {
return nil, fmt.Errorf("cannot open file %q: %w", indexFilePath, err)
}
}
if !h.generateIndexPages {
return nil, fmt.Errorf("cannot access directory without index page: directory %q", dirPath)
}
return h.createDirIndex(ctx, dirPath, mustCompress, fileEncoding)
}
var (
errDirIndexRequired = errors.New("directory index required")
errNoCreatePermission = errors.New("no 'create file' permissions")
)
func (h *fsHandler) createDirIndex(ctx *RequestCtx, dirPath string, mustCompress bool, fileEncoding string) (*fsFile, error) {
w := &bytebufferpool.ByteBuffer{}
base := ctx.URI()
// io/fs doesn't support ReadDir with empty path.
if dirPath == "" {
dirPath = "."View on GitHub (pinned to c96f600972)
Solutions
- Ship an index file (index.html) into every servable directory, or
- Set GenerateIndexPages: true if auto-generated directory listings are acceptable for your security posture
- Add your actual index filename to Config.IndexNames (e.g. []string{"index.htm", "default.html"}) so it is found
- Restructure URLs so users never hit bare directories (link directly to files)
Example fix
// before
h := fs.New(fs.Config{Root: "./static", GenerateIndexPages: false})
// after — either ship index.html, or allow generated listings
h := fs.New(fs.Config{Root: "./static", GenerateIndexPages: true, IndexNames: []string{"index.html", "index.htm"}}) Defensive patterns
Strategy: fallback
Validate before calling
cfg := fs.Config{IndexNames: []string{"index.html", "index.htm"}, GenerateIndexPages: true}
for _, dir := range []string{"./static", "./static/sub"} {
if _, err := os.Stat(filepath.Join(dir, "index.html")); err != nil {
log.Printf("missing index in %s", dir)
}
} Type guard
func hasIndexFile(dir string, names []string) bool {
for _, n := range names {
if _, err := os.Stat(filepath.Join(dir, n)); err == nil { return true }
}
return false
} Try / catch
if err := fileHandler(ctx); err != nil {
if strings.Contains(err.Error(), "without index page") {
http.Error(ctx, "Forbidden", http.StatusForbidden)
}
} Prevention
- Keep GenerateIndexPages: true unless you guarantee index files everywhere
- List every real index filename in Config.IndexNames
- Add a CI/build check that each servable directory contains an index file
- Deep-link to files instead of directory URLs when indexes are disabled
When it happens
Trigger: Requesting a directory URL (e.g. GET /subdir/) against fs.New(fs.Config{... GenerateIndexPages: false ...}) when no index.html (or configured indexNames) exists in that directory; direct handler.openIndexFile calls with mustCompress contexts and no index file present.
Common situations: Deployments that disable generated index pages for security but forget to ship index.html into each directory; misconfigured indexNames so the real index file is never looked up; static sites where only some directories have index files.
Related errors
- cannot open already opened file: %w
- cannot open file %q: %w
- fasthttp: no args value for the given key
- fasthttp: pipelined requests' queue has been overflowed. inc
- pipeline connection has been stopped
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/4fc95a521a80eb62.
Report an issue: GitHub.