Panniantong/Agent-Reach · error · PrivatePathError
读取目标不是常规文件:{target}
Error message
读取目标不是常规文件:{target} What it means
Raised by the O_NOFOLLOW private file reader when the opened file descriptor's fstat shows the target is not a regular file (not S_ISREG). The file was opened with O_NOFOLLOW so a symlink final component would have failed at open; this check catches everything else: directories, device nodes, FIFOs, sockets. Message (Chinese): 'read target is not a regular file: {target}'.
Source
Thrown at agent_reach/utils/paths.py:164
if max_bytes < 0:
raise ValueError("max_bytes must be non-negative")
target = ensure_no_symlink_path(path, "读取路径")
flags = (
os.O_RDONLY
| getattr(os, "O_NOFOLLOW", 0)
| getattr(os, "O_NONBLOCK", 0)
| getattr(os, "O_CLOEXEC", 0)
)
try:
fd = os.open(target, flags)
except FileNotFoundError:
return None
try:
file_stat = os.fstat(fd)
if not stat.S_ISREG(file_stat.st_mode):
raise PrivatePathError(f"读取目标不是常规文件:{target}")
if file_stat.st_size > max_bytes:
raise PrivatePathError(f"读取目标超过大小上限:{target}")
chunks = []
remaining = max_bytes + 1
while remaining:
chunk = os.read(fd, remaining)
if not chunk:
break
chunks.append(chunk)
remaining -= len(chunk)
payload = b"".join(chunks)
if len(payload) > max_bytes:
raise PrivatePathError(f"读取目标超过大小上限:{target}")
ensure_no_symlink_path(target, "读取路径")
finally:
os.close(fd)
return payload.decode(encoding)View on GitHub (pinned to 93ae1d18c3)
Solutions
- Check the caller: ensure you pass a file path, not its parent directory
- Verify with Path(target).is_file() (or os.path.isfile) before invoking the read helper in your own glue code
- If a FIFO/socket sits at the expected file path, remove it and let the app recreate the real file
Example fix
# before
data = read_private_file("~/.config/agent-reach") # that's the directory
# after
data = read_private_file("~/.config/agent-reach/credentials.yaml") Defensive patterns
Strategy: type-guard
Validate before calling
import os
def is_regular_file(path: str) -> bool:
try:
return os.path.isfile(path) # True only for regular files (follows no special nodes)
except (OSError, ValueError):
return False Type guard
import stat, os
def is_regular_file_strict(path: str) -> bool:
"""True when path exists and is a regular file (not dir/fifo/socket/device)."""
try:
return stat.S_ISREG(os.stat(path).st_mode)
except OSError:
return False Try / catch
from agent_reach.utils.paths import PrivatePathError
try:
payload = read_private(target, max_bytes=cap)
except PrivatePathError as e:
if "常规文件" in str(e):
target = find_real_file(target) # e.g. append the expected filename
payload = read_private(target, max_bytes=cap)
else:
raise Prevention
- Assert is_regular_file() on user- or glob-supplied paths before reading
- Log the path (not contents) on failure to spot directory-vs-file mixups fast
- In tests, always create real files, never FIFOs/symlinks, under the private dir
When it happens
Trigger: Passing a directory path, a named pipe, /dev/null or another device node to the private read helper (the function that takes max_bytes). Happens when a glob or user input yields a non-file path.
Common situations: Passing a config/cache path that is actually a directory (e.g. the private dir itself instead of a file inside it); Unix tools creating FIFOs at expected file locations; glob patterns matching sockets in runtime dirs.
Related errors
- {label}不能经过符号链接:{current}
- 读取目标超过大小上限:{target}
- gh hosts.yml 无法安全读取
- mcporter 配置文件无法安全读取:{exc}
- mcporter 配置文件无法安全读取
AI-assisted analysis of Panniantong/Agent-Reach@93ae1d18c3 (2026-08-14).
Data as JSON: /api/errors/8554fb3ca8bfe3a0.
Report an issue: GitHub.