binary-husky/gpt_academic · error · PermissionError

No read permission: {path}

Error message

No read permission: {path}

What it means

UnstructuredReader's English counterpart of the permission check: raised when os.access(path, os.R_OK) is False even though the file exists. Mirrors paper_metadata_extractor's Chinese variant so both readers behave identically.

Source

Thrown at crazy_functions/doc_fns/read_fns/unstructured_all/unstructured_reader.py:121

            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

    def _cleanup_text(self, text: str) -> str:
        """清理文本

View on GitHub (pinned to d6bde0fa54)

Solutions

  1. chmod a+r or chown the file to the service user, then retry.
  2. Align UIDs between the container/process and the volume owner (docker run -u, user: in compose).
  3. Check ACLs (getfacl) and SELinux context (ls -Z) when plain chmod doesn't help.
  4. Copy the file to a process-owned temp dir before reading if permissions cannot be changed.

Example fix

# before
text = reader.read('/srv/secure/paper.pdf')  # PermissionError

# after
import shutil, tempfile
if not os.access(p, os.R_OK):
    tmp = Path(tempfile.mkdtemp()) / Path(p).name
    shutil.copy(p, tmp)  # run where rights exist, or pre-fix modes
    p = tmp
text = reader.read(p)
Defensive patterns

Strategy: validation

Validate before calling

import os
if not os.access(os.path.realpath(fp), os.R_OK):
    fix_perms_or_copy_to_tmp(fp)

Type guard

def readable(path: str) -> bool:
    import os
    return os.path.isfile(path) and os.access(path, os.R_OK)

Try / catch

try:
    reader.read(fp)
except PermissionError as e:
    log_warning(f'no read access: {e}')
    skip_file(fp)

Prevention

When it happens

Trigger: Same as the Chinese variant: file present, is_file() true, but the effective UID/GID lacks read permission — chmod 600 owned by another user, restrictive ACL, files created by a root process, or root_squash on NFS denying root readers.

Common situations: Multi-user deployments where uploads are owned by the web user but analysis runs under a worker user; Docker containers with mismatched UID; SELinux/AppArmor denials that manifest as EACCES; files restored from an archive with 000 mode.

Related errors


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