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

  1. Ship an index file (index.html) into every servable directory, or
  2. Set GenerateIndexPages: true if auto-generated directory listings are acceptable for your security posture
  3. Add your actual index filename to Config.IndexNames (e.g. []string{"index.htm", "default.html"}) so it is found
  4. 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

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


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