yorukot/superfile · error

failed to open source file: %w

Error message

failed to open source file: %w

What it means

copyFile wraps os.Open(src) failures when opening the source file for reading during a copy. Typical wrapped causes are ENOENT (file gone) and EACCES (no read permission). The copy of that single file fails immediately.

Source

Thrown at src/internal/file_operations.go:140

// is an equivalent of "cp -P" command
func copyLinkFile(src, dst string) error {
	target, err := os.Readlink(src)
	if err != nil {
		return err
	}
	return os.Symlink(target, dst)
}

func isSymlink(info os.FileInfo) bool {
	return info.Mode()&os.ModeSymlink != 0
}

// copyFile copies a single file
func copyFile(src, dst string, srcInfo os.FileInfo) error {
	srcFile, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("failed to open source file: %w", err)
	}
	defer srcFile.Close()

	dstFile, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, srcInfo.Mode())
	if err != nil {
		return fmt.Errorf("failed to create destination file: %w", err)
	}
	defer dstFile.Close()

	if _, err := io.Copy(dstFile, srcFile); err != nil {
		return fmt.Errorf("failed to copy file contents: %w", err)
	}
	return nil
}

// pasteDir handles directory copying with progress tracking
func pasteDir(src, dst string, p *processbar.Process, cut bool, processBarModel *processbar.Model) error {
	dst, err := renameIfDuplicate(dst)

View on GitHub (pinned to b72f550bc6)

Solutions

  1. Verify the source file exists (ls or os.Stat) and re-select it if it was moved or deleted.
  2. Fix read permissions: chmod u+r (or chown) so the running user can read the file.
  3. If running with elevated context lost (e.g. sudo copy earlier), re-copy with correct ownership.
  4. Retry the paste; if it recurs, check for processes deleting files concurrently.

Example fix

// before
err := ops.CopyFile(srcPath, dstPath)
// after
if _, statErr := os.Stat(srcPath); errors.Is(statErr, fs.ErrNotExist) {
    return fmt.Errorf("source %s no longer exists; refresh selection and retry", srcPath)
}
if err := ops.CopyFile(srcPath, dstPath); err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrPermission) {
        return fmt.Errorf("cannot read %s: fix permissions (%w)", srcPath, err)
    }
    return err
}
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(src)
if err != nil {
    return fmt.Errorf("source unavailable: %w", err)
}
if info.IsDir() {
    return fmt.Errorf("%s is a directory, not a file", src)
}
f, err := os.OpenFile(src, os.O_RDONLY, 0)
if err != nil {
    return fmt.Errorf("source not readable: %w", err)
}
f.Close()

Try / catch

if err := ops.CopyFile(src, dst); err != nil {
    if errors.Is(err, fs.ErrNotExist) { /* refresh selection */ }
    if errors.Is(err, fs.ErrPermission) { /* fix chmod */ }
    return err
}

Prevention

When it happens

Trigger: copyElement, copyDir or actualPasteOperation calls copyFile with a src path that was deleted after the directory listing, or a file the user cannot read (mode 0600 owned by another user, or read permission removed).

Common situations: Pasting files after the original was deleted or renamed; copying files with restrictive permissions; reading from a mount whose contents changed; a file locked/deleted by another process.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


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