yorukot/superfile · error

failed to stat source: %w

Error message

failed to stat source: %w

What it means

copyElement starts by calling os.Stat(src) to learn whether the source is a file or directory; any Stat failure is wrapped as 'failed to stat source'. It means the source path does not exist or is inaccessible before any copying begins.

Source

Thrown at src/internal/file_operations.go:81

	// If on different partitions or rename failed, fall back to copy+delete
	err = copyElement(src, dst)
	if err != nil {
		return fmt.Errorf("failed to copy: %w", err)
	}

	err = os.RemoveAll(src)
	if err != nil {
		return fmt.Errorf("failed to remove source after copy: %w", err)
	}

	return nil
}

// copyElement handles copying of both files and directories
func copyElement(src, dst string) error {
	srcInfo, err := os.Stat(src)
	if err != nil {
		return fmt.Errorf("failed to stat source: %w", err)
	}

	if srcInfo.IsDir() {
		return copyDir(src, dst, srcInfo)
	}
	return copyFile(src, dst, srcInfo)
}

// copyDir recursively copies a directory
func copyDir(src, dst string, srcInfo os.FileInfo) error {
	err := os.MkdirAll(dst, srcInfo.Mode())
	if err != nil {
		return fmt.Errorf("failed to create destination directory: %w", err)
	}

	entries, err := os.ReadDir(src)
	if err != nil {
		return fmt.Errorf("failed to read source directory: %w", err)

View on GitHub (pinned to b72f550bc6)

Solutions

  1. Verify the source path exists (ls / os.Stat) before calling the move/copy API.
  2. Fix parent directory permissions so the path is traversable.
  3. If the source was a broken symlink, remove it or point it at a real target.
  4. Retry if this was a transient race; serialize concurrent operations on the same tree.

Example fix

// before
if _, err := os.Stat(src); err != nil { return } // not checked by caller
// after
if _, err := os.Stat(src); err == nil {
    moveElement(src, dst)
}
Defensive patterns

Strategy: validation

Validate before calling

srcInfo, err := os.Stat(src)
if err != nil {
    return fmt.Errorf("refusing to copy: source %q unavailable: %w", src, err)
}
_ = srcInfo // safe to proceed to copyElement

Type guard

func sourceReady(src string) bool {
    st, err := os.Stat(src)
    return err == nil && (st.Mode().Perm()&0444 != 0 || st.IsDir())
}

Try / catch

if err := copyElement(src, dst); err != nil {
    var pErr *fs.PathError
    if errors.As(err, &pErr) && errors.Is(pErr.Err, fs.ErrNotExist) {
        log.Errorf("Source vanished: %s", pErr.Path)
        return fs.ErrNotExist // skip gracefully instead of failing the batch
    }
    return err
}

Prevention

When it happens

Trigger: moveElement -> copyElement where src was deleted/moved between the partition check and the copy, or src never existed / lacks parent-directory execute permission.

Common situations: Race where another process removed the source during the move; symlink to a nonexistent target; path typo; running without traverse permission on a parent directory.

Related errors


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