binary-husky/gpt_academic · error · ValueError
Not a file: {path}
Error message
Not a file: {path} What it means
Raised by UnstructuredReader._validate_file when the path exists but is not a regular file (path.is_file() is False) — i.e. it is a directory, a symlink to a directory, or a special file (fifo/socket/device). Distinct from 'File not found' which fires earlier for missing paths.
Source
Thrown at crazy_functions/doc_fns/read_fns/unstructured_all/unstructured_reader.py:118
Args:
file_path: 文件路径
max_size_mb: 允许的最大文件大小(MB)
Returns:
Path: 验证后的Path对象
Raises:
ValueError: 文件不存在、格式不支持或大小超限
PermissionError: 没有读取权限
"""
path = Path(file_path).resolve()
if not path.exists():
raise ValueError(f"File not found: {path}")
if not path.is_file():
raise ValueError(f"Not a file: {path}")
if not os.access(path, os.R_OK):
raise PermissionError(f"No read permission: {path}")
file_size_mb = path.stat().st_size / (1024 * 1024)
if file_size_mb > max_size_mb:
raise ValueError(
f"File size ({file_size_mb:.1f}MB) exceeds limit of {max_size_mb}MB"
)
if path.suffix.lower() not in self.SUPPORTED_EXTENSIONS:
raise ValueError(
f"Unsupported format: {path.suffix}. "
f"Supported: {', '.join(sorted(self.SUPPORTED_EXTENSIONS))}"
)
return path
View on GitHub (pinned to d6bde0fa54)
Solutions
- Filter to regular files before calling: iterate p for p in Path(d).iterdir() if p.is_file().
- If a directory was intended, expand it to its supported files and call the reader per file.
- Resolve symlinks (Path.resolve()) and re-check is_file() to catch links to directories.
- Validate user-supplied paths against a whitelist root to reject odd paths early.
Example fix
# before reader.read(user_path) # ValueError if user_path is a directory # after p = Path(user_path).resolve() paths = [c for c in p.iterdir() if c.is_file()] if p.is_dir() else [p] texts = [reader.read(c) for c in paths]
Defensive patterns
Strategy: type-guard
Validate before calling
from pathlib import Path p = Path(user_path).resolve() paths = sorted(p.iterdir()) if p.is_dir() else [p] paths = [c for c in paths if c.is_file()]
Type guard
def is_regular_file(path: str) -> bool:
from pathlib import Path
return Path(path).is_file() Try / catch
try:
reader.read(fp)
except ValueError as e:
if str(e).startswith('Not a file'):
expand_dir_to_files(fp) # user passed a folder
raise Prevention
- Expand directories to file lists before processing.
- Resolve() symlinks and re-check is_file().
- Validate user paths against a whitelist root.
- Use p.iterdir() filters with is_file() in batch loops.
When it happens
Trigger: Passing a directory path to the reader (e.g. pointing at a folder of PDFs instead of one file); passing /dev/null or a named pipe; passing a symlink chain that ends at a directory; passing a broken special path like a Windows junction.
Common situations: UI accepting either a file or folder and forwarding it unchecked; glob patterns that match a directory ('data' instead of 'data/*.pdf'); symlinks in shared storage pointing at folders; automated pipelines iterating os.listdir output that includes subdirectories.
Related errors
- File not found: {path}
- 没有读取权限: {path}
- No read permission: {path}
- 文件大小 ({file_size_mb:.1f}MB) 超过限制 {max_size_mb}MB
- 文件大小 ({file_size_mb:.1f}MB) 超过限制 {max_size_mb}MB
AI-assisted analysis of binary-husky/gpt_academic@d6bde0fa54 (2026-08-14).
Data as JSON: /api/errors/1e7325b1d5dfb835.
Report an issue: GitHub.