binary-husky/gpt_academic · error · ValueError

Not a file: {path}

Error message

Not a file: {path}

What it means

Second check in ExcelTextExtractor._validate_file: the path exists (previous check passed) but is not a regular file — it is a directory, socket, fifo, or symlink-to-device. Raises ValueError('Not a file: <path>'). Exists-but-not-file is exactly the discrimination this check provides.

Source

Thrown at crazy_functions/doc_fns/read_fns/excel_reader.py:76

            return self.config.encoding

        try:
            with open(file_path, 'rb') as f:
                raw_data = f.read(10000)
                result = chardet.detect(raw_data)
                return result['encoding'] or 'utf-8'
        except Exception as e:
            self.logger.warning(f"Encoding detection failed: {e}. Using utf-8")
            return 'utf-8'

    def _validate_file(self, file_path: Union[str, Path]) -> Path:
        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}")

        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

    def _format_value(self, value: Any) -> str:
        if pd.isna(value) or value is None:
            return ''
        if isinstance(value, (int, float)):
            return str(value)
        return str(value).strip()

View on GitHub (pinned to d6bde0fa54)

Solutions

  1. If a directory was intended, enumerate files first and call the reader per file (filter with path.is_file())
  2. Inspect with ls -la / pathlib to see what the path actually is
  3. Validate selection type in the UI/frontend before submission

Example fix

// before
extractor.read_text('my_folder')  # ValueError: Not a file

// after
for f in sorted(Path('my_folder').glob('*.xlsx')):
    if f.is_file():
        extractor.read_text(f)
Defensive patterns

Strategy: type-guard

Validate before calling

from pathlib import Path

fp = Path(target)
assert fp.is_file(), f'expected a file, got: {fp}'

Type guard

from pathlib import Path

def is_regular_file(p) -> bool:
    p = Path(p)
    return p.is_file() and not p.is_dir() and not p.is_symlink() or (p.is_symlink() and p.resolve().is_file())

Try / catch

try:
    text = extractor.read_text(fp)
except ValueError as e:
    if str(e).startswith('Not a file'):
        if fp.is_dir():
            for f in fp.glob('*'): process(f)  # recover: iterate directory
        else: raise

Prevention

When it happens

Trigger: Passing a directory path (e.g. the folder containing spreadsheets instead of one file); a dangling special file; /dev/null style paths; a symlink pointing to a directory.

Common situations: UI flows where users select a folder; glob results that matched a directory named 'data.csv/'; confusing archive extraction that created 'report.xlsx/' as a directory.

Related errors


AI-assisted analysis of binary-husky/gpt_academic@d6bde0fa54 (2026-08-14). Data as JSON: /api/errors/633e3b20caf4b07d. Report an issue: GitHub.