yorukot/superfile · error

the file is not readable: %s

Error message

the file is not readable: %s

What it means

validateCompressOperation found a non-directory source file that fails the checkFileReadable test, meaning it cannot be opened for reading (unreadable permissions or a special file that can't be read like a named pipe opened exclusively). The compression is aborted.

Source

Thrown at src/internal/file_operations_compress.go:33

	"github.com/yorukot/superfile/src/internal/ui/notify"
	"github.com/yorukot/superfile/src/internal/ui/processbar"
)

func validateCompressOperation(sources []string) (int, error) {
	totalFiles := 0
	for _, src := range sources {
		stat, err := os.Stat(src)
		if os.IsNotExist(err) {
			return 0, fmt.Errorf("source path does not exist: %s", src)
		}
		if err != nil {
			return 0, fmt.Errorf("cannot access source path %s: %w", src, err)
		}
		if !stat.IsDir() {
			if err = checkFileReadable(src); err != nil {
				slog.Error("the file is not readable", "error", err)
				return 0, fmt.Errorf("the file is not readable: %s", err.Error())
			}
		}
		count, err := countReadableFiles(src)
		if err != nil {
			slog.Error("Error while zip file count files ", "error", err)
			return 0, fmt.Errorf("error while counting files for %s: %s", src, err.Error())
		}
		totalFiles += count
	}
	return totalFiles, nil
}

func (m *model) getCompressSelectedFilesCmd() tea.Cmd {
	panel := m.getFocusedFilePanel()

	if panel.Empty() {
		return nil
	}

View on GitHub (pinned to b72f550bc6)

Solutions

  1. Check the file mode (ls -l) and grant read access: chmod u+r <file>.
  2. Remove unreadable or special files from the selection list before compressing.
  3. If the file should be readable, fix ownership: sudo chown <user> <file>.
  4. Verify with a pre-flight read test (os.OpenFile(path, O_RDONLY, 0)) before calling the library.

Example fix

// before
sources = append(sources, newPath)
// after
f, err := os.OpenFile(newPath, os.O_RDONLY, 0)
if err != nil {
    slog.Warn("skipping unreadable source", "path", newPath, "err", err)
} else {
    f.Close()
    sources = append(sources, newPath)
}
Defensive patterns

Strategy: validation

Validate before calling

f, err := os.OpenFile(src, os.O_RDONLY, 0)
if err != nil {
    return fmt.Errorf("skipping unreadable file %s: %w", src, err)
}
f.Close()

Try / catch

if err := ops.ZipSources(sources, target); err != nil {
    if strings.Contains(err.Error(), "not readable") {
        // drop that file from the list or fix its permissions, then retry
    }
    return err
}

Prevention

When it happens

Trigger: A source in the list is a regular file with no read permission bit for the current user (e.g. mode 000, or owned by root), or a special file checkFileReadable rejects.

Common situations: Selecting files created by another user/root with restrictive modes; files with ACLs blocking read; sockets/pipes accidentally included in a selection.

Related errors


AI-assisted analysis of yorukot/superfile@b72f550bc6 (2026-09-01). Data as JSON: /api/errors/6293c3e75f8b8ee5. Report an issue: GitHub.