larksuite/cli · error

not a regular file (directories, devices, FIFOs, and sockets

Error message

not a regular file (directories, devices, FIFOs, and sockets are refused)

What it means

The opened handle points to something that is not a regular file — a directory, device, FIFO, or socket. The library only serves regular files through validated opens, so any other file type is refused after opening. This prevents reading from special objects or directories through the file API.

Source

Thrown at internal/vfs/localfileio/openvalidated_windows.go:50

		// map ErrPathValidation to a typed validation error, and the fd checks
		// are the same verdict the path checks make, one layer later.
		return nil, &fileio.PathValidationError{Err: err}
	}
	return f, nil
}

// inspectOpenedFile validates the opened handle. pre is nil when there is no
// prior Stat to compare against.
func inspectOpenedFile(f *os.File, pre os.FileInfo) error {
	post, err := f.Stat()
	if err != nil {
		return fmt.Errorf("cannot stat opened file: %w", err)
	}
	if pre != nil && !os.SameFile(pre, post) {
		return fmt.Errorf("file changed between validation and open")
	}
	if !post.Mode().IsRegular() {
		return fmt.Errorf("not a regular file (directories, devices, FIFOs, and sockets are refused)")
	}
	var handleInfo syscall.ByHandleFileInformation
	if err := syscall.GetFileInformationByHandle(syscall.Handle(f.Fd()), &handleInfo); err != nil {
		return fmt.Errorf("cannot inspect opened file links: %w", err)
	}
	if handleInfo.NumberOfLinks > 1 {
		return fmt.Errorf("file has multiple hard links, so the other names it can be reached by " +
			"cannot be checked (hint: copy the file and use the copy instead)")
	}
	return nil
}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Check the path with os.Stat and require stat.Mode().IsRegular() before calling
  2. Remove any trailing path separator or wrong component so the path names the actual file, not its directory
  3. Do not open device, pipe, or socket paths through this API; use the appropriate OS-specific mechanism instead
  4. If input comes from users/config, validate the resolved path points at an expected regular file

Example fix

// before: no type check
f, err := openValidated(userPath, nil)
// after
info, err := os.Stat(userPath)
if err != nil { return err }
if !info.Mode().IsRegular() {
    return fmt.Errorf("%s is not a regular file", userPath)
}
f, err := openValidated(userPath, info)
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(path)
if err != nil { return err }
if !info.Mode().IsRegular() {
    return fmt.Errorf("refusing non-regular path %s (mode %s)", path, info.Mode())
}

Type guard

func isRegularFile(info os.FileInfo) bool { return info != nil && info.Mode().IsRegular() }

Try / catch

f, err := openValidated(path, pre)
if err != nil && strings.Contains(err.Error(), "not a regular file") {
    return fmt.Errorf("%s is a directory or special file; provide a path to a regular file", path)
}

Prevention

When it happens

Trigger: Passing a directory path, a device path (e.g. \\.\PhysicalDrive0, NUL), a named pipe, or a unix-domain socket path to openValidated on Windows.

Common situations: Constructing a path from user input that points at a directory, accidentally passing a COM port or device namespace path, pointing the CLI at a socket file created by a local server, or misconfigured workspace/file settings.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/67eb389b138ca584. Report an issue: GitHub.