valyala/fasthttp · info
directory index required
Error message
directory index required
What it means
errDirIndexRequired signals that the requested path resolved to a directory and fasthttp must generate (and possibly cache) a directory index listing instead of serving a file. It is an internal sentinel used to redirect control flow into createDirIndex.
Source
Thrown at fs.go:1564
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 = "."
}
basePathEscaped := html.EscapeString(string(base.Path()))
_, _ = fmt.Fprintf(w, "<html><head><title>%s</title><style>.dir { font-weight: bold }</style></head><body>", basePathEscaped)
_, _ = fmt.Fprintf(w, "<h1>%s</h1>", basePathEscaped)
_, _ = fmt.Fprintf(w, "<ul>")
View on GitHub (pinned to c96f600972)
Solutions
- Point the request at a concrete file, or add an index file (index.html) to the directory
- Set IndexNames on fs.Handler (e.g. fs.IndexNames = []string{"index.html"}) so directories resolve to index files
- Allow index generation (GenerateIndexPages=true) so fasthttp can build the listing
- Handle/inspect the sentinel if you embed fs internals and call serveFile directly
Example fix
// before
h := &fasthttp.Fs{Root: "./static"} // directory hits produce generated index
// after
h := &fasthttp.Fs{Root: "./static", IndexNames: []string{"index.html"}, GenerateIndexPages: true} Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(fsPath)
if err == nil && info.IsDir() {
// ensure an index file exists or generation is enabled
} Type guard
func isDirIndexSentinel(err error) bool {
return err != nil && err.Error() == "directory index required"
} Try / catch
if err := handler(ctx); err != nil && errors.Is(err, fasthttp.ErrDirIndexRequiredLike) {
// handle directory case explicitly
} Prevention
- Always ship an index.html in served directories and list it in fs.IndexNames
- Set GenerateIndexPages=true if directory listings are acceptable
- Never point Root at an empty directory in production
- Sanity-check the URI-to-path mapping in custom path rewriters
When it happens
Trigger: An fsHandler RequestHandler receives a URI whose fsPath maps to a directory and no index/default file applies, so serveFile returns this sentinel and the handler builds the directory listing.
Common situations: Requesting a directory URL without trailing index file; misconfigured Root pointing at a directory; Compress/GenerateIndexPages interplay causing index generation paths.
Related errors
- must implement readat
- no 'create file' permissions
- must implement seek
- seek is not implemented
- fasthttp: contain forbidden trailer
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/987f8fd8d190e995.
Report an issue: GitHub.