kovidgoyal/kitty · warning

failed to read the directory %s with error: %w

Error message

failed to read the directory %s with error: %w

What it means

NewDirectoryPreview could not os.ReadDir the directory being previewed, and returns an error preview instead of a listing. The path exists per earlier stat, but reading it failed at this moment.

Source

Thrown at kittens/choose_files/preview.go:173

		}
		type_map := make(map[string]entry, len(entries))
		for _, e := range entries {
			type_map[e.Name()] = entry{strings.ToLower(e.Name()), e.Type()}
		}
		names := utils.Map(func(e fs.DirEntry) string { return e.Name() }, entries)
		slices.SortFunc(names, func(a, b string) int { return strings.Compare(type_map[a].lname, type_map[b].lname) })
		fmt.Fprintln(&buf, "Contents:")
		for _, n := range names {
			trailers = append(trailers, icons.IconForFileWithMode(n, type_map[n].ftype, false)+"  "+sanitize(n))
		}
	}
	return buf.String(), trailers
}

func NewDirectoryPreview(abspath string, metadata fs.FileInfo) Preview {
	entries, err := os.ReadDir(abspath)
	if err != nil {
		return NewErrorPreview(fmt.Errorf("failed to read the directory %s with error: %w", abspath, err))
	}
	title := icons.IconForFileWithMode("dir", fs.ModeDir, false) + "  Directory\n"
	header, extra := write_file_metadata(abspath, metadata, entries)
	return &MessagePreview{title: title, msg: header, trailers: extra}
}

func NewFileMetadataPreview(abspath string, metadata fs.FileInfo) *MessagePreview {
	ext := filepath.Ext(abspath)
	if ext == "" {
		ext = "File"
	}
	title := icons.IconForFileWithMode(filepath.Base(abspath), metadata.Mode().Type(), false) + "  " + ext
	h, t := write_file_metadata(abspath, metadata, nil)
	return &MessagePreview{title: title, msg: h, trailers: t}
}

func NewFileMetadataPreviewWithError(abspath string, metadata fs.FileInfo, err error) *MessagePreview {
	ext := filepath.Ext(abspath)

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Check permissions on the directory (need read+execute for listing)
  2. If the dir was deleted, refresh the file list in the chooser
  3. For FUSE/network mounts, verify the mount is alive

Example fix

// before
entries, err := os.ReadDir(abspath)
// after
entries, err := os.ReadDir(abspath)
if err != nil {
    if errors.Is(err, fs.ErrPermission) {
        return NewErrorPreview(fmt.Errorf("no permission to list %s", abspath))
    }
    return NewErrorPreview(fmt.Errorf("failed to read the directory %s with error: %w", abspath, err))
}
Defensive patterns

Strategy: try-catch

Validate before calling

if f, err := os.Stat(dir); err != nil || !f.IsDir() { /* skip preview */ }

Try / catch

if err := os.ReadDir(dir); err != nil { if errors.Is(err, fs.ErrPermission) { show 'no permission' preview } else { show generic error preview } }

Prevention

When it happens

Trigger: preview_for -> NewDirectoryPreview where os.ReadDir(abspath) errors: permission denied on execute/search of the directory, directory removed between selection and preview, or special filesystems (e.g. /proc entries, broken FUSE mounts).

Common situations: Previewing a directory without +x permission; directory deleted while the chooser is open; NFS/FUSE mount hiccups; dangling symlinks to directories.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/4021b3c3e6ee2be2. Report an issue: GitHub.