{"record":{"id":"05cbb1fe3b96cbe3","repo":"binary-husky/gpt_academic","slug":"path-05cbb1","errorCode":null,"errorMessage":"没有读取权限: {path}","messagePattern":"没有读取权限: (.+?)","errorType":"exception","errorClass":"PermissionError","httpStatus":null,"severity":"error","filePath":"crazy_functions/doc_fns/read_fns/unstructured_all/paper_metadata_extractor.py","lineNumber":110,"sourceCode":"            max_size_mb: 允许的最大文件大小(MB)\n\n        Returns:\n            Path: 验证后的Path对象\n\n        Raises:\n            ValueError: 文件不存在、格式不支持或大小超限\n            PermissionError: 没有读取权限\n        \"\"\"\n        path = Path(file_path).resolve()\n\n        if not path.exists():\n            raise ValueError(f\"文件不存在: {path}\")\n\n        if not path.is_file():\n            raise ValueError(f\"不是文件: {path}\")\n\n        if not os.access(path, os.R_OK):\n            raise PermissionError(f\"没有读取权限: {path}\")\n\n        file_size_mb = path.stat().st_size / (1024 * 1024)\n        if file_size_mb > max_size_mb:\n            raise ValueError(\n                f\"文件大小 ({file_size_mb:.1f}MB) 超过限制 {max_size_mb}MB\"\n            )\n\n        if path.suffix.lower() not in self.SUPPORTED_EXTENSIONS:\n            raise ValueError(\n                f\"不支持的文件格式: {path.suffix}. \"\n                f\"支持的格式: {', '.join(sorted(self.SUPPORTED_EXTENSIONS))}\"\n            )\n\n        return path\n\n    def _cleanup_text(self, text: str) -> str:\n        \"\"\"清理文本\n","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/binary-husky/gpt_academic/blob/d6bde0fa54373309bd05823a49bda8da019d2c77/crazy_functions/doc_fns/read_fns/unstructured_all/paper_metadata_extractor.py#L92-L128","documentation":"Raised by PaperMetadataExtractor._validate_file when the resolved path exists and is a regular file, but the current process lacks read permission (os.access(path, os.R_OK) is False). It is a deliberate pre-flight check before any parsing work so the caller gets a precise PermissionError instead of a cryptic parser failure.","triggerScenarios":"Calling extract/metadata APIs of PaperMetadataExtractor with a file path whose mode bits (or owning user/group) deny read to the running process — e.g. chmod 000/chmod 600 file owned by another user, or a file created by root while the app runs as an unprivileged user.","commonSituations":"Running the service as a different user than the one that downloaded/uploaded files; files staged by a root cron job or Docker container with restrictive umask; ACLs on mounted/network volumes (NFS root_squash); read-only bind mounts without read rights.","solutions":["Fix permissions on the file: chmod a+r <file> or chown to the running user, then retry.","If the app runs under a service account, ensure uploaded/generated files are chowned to that account (e.g. in the upload handler).","When using Docker/NFS, verify volume mount options and ACLs grant read to the container user.","As a last resort, run the reader in a subprocess as a user with rights, or copy the file to a readable temp location first."],"exampleFix":"# before\nmeta = extractor.extract('/data/papers/root-owned.pdf')  # PermissionError\n\n# after\nimport os, stat\np = '/data/papers/root-owned.pdf'\nif not os.access(p, os.R_OK):\n    os.chmod(p, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)\nmeta = extractor.extract(p)","handlingStrategy":"validation","validationCode":"import os\np = os.path.realpath(file_path)\nif not os.access(p, os.R_OK):\n    raise PermissionError(f'fix perms first: {p}')","typeGuard":"def is_readable(path: str) -> bool:\n    import os\n    return os.path.exists(path) and os.path.isfile(path) and os.access(path, os.R_OK)","tryCatchPattern":"try:\n    extractor.extract(fp)\nexcept PermissionError as e:\n    log_warning(f'perms: {e}'); skip_file(fp)  # do not retry blindly","preventionTips":["Run the service under the user that owns uploaded files.","Set explicit umask/mode on files at write time (e.g. 0o644).","Pre-check os.access(path, os.R_OK) before calling the extractor.","Audit volume ACLs when deploying to NFS/Docker."],"tags":["filesystem","permissions","validation","python"],"backgroundTag":null,"analyzedSha":"d6bde0fa54373309bd05823a49bda8da019d2c77","analyzedAt":"2026-08-14T22:48:35.038Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}