{"id":"bc534d593f74a2e4","repo":"pypa/pip","slug":"os-rename-and-os-unlink-are-not-supported-on-t","errorCode":null,"errorMessage":"\"os.rename\" and \"os.unlink\" are not supported on this platform","messagePattern":"\"os\\.rename\" and \"os\\.unlink\" are not supported on this platform","errorType":"exception","errorClass":"OSError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/pkg_resources/__init__.py","lineNumber":2042,"sourceCode":"        size = zip_stat.file_size\n        # ymdhms+wday, yday, dst\n        date_time = zip_stat.date_time + (0, 0, -1)\n        # 1980 offset already done\n        timestamp = time.mktime(date_time)\n        return timestamp, size\n\n    # FIXME: 'ZipProvider._extract_resource' is too complex (12)\n    def _extract_resource(self, manager: ResourceManager, zip_path) -> str:  # noqa: C901\n        if zip_path in self._index():\n            for name in self._index()[zip_path]:\n                last = self._extract_resource(manager, os.path.join(zip_path, name))\n            # return the extracted directory name\n            return os.path.dirname(last)\n\n        timestamp, size = self._get_date_and_size(self.zipinfo[zip_path])\n\n        if not WRITE_SUPPORT:\n            raise OSError(\n                '\"os.rename\" and \"os.unlink\" are not supported on this platform'\n            )\n        try:\n            if not self.egg_name:\n                raise OSError(\n                    '\"egg_name\" is empty. This likely means no egg could be found from the \"module_path\".'\n                )\n            real_path = manager.get_cache_path(self.egg_name, self._parts(zip_path))\n\n            if self._is_current(real_path, zip_path):\n                return real_path\n\n            outf, tmpnam = _mkstemp(\n                \".$extract\",\n                dir=os.path.dirname(real_path),\n            )\n            os.write(outf, self.loader.get_data(zip_path))\n            os.close(outf)","sourceCodeStart":2024,"sourceCodeEnd":2060,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/pkg_resources/__init__.py#L2024-L2060","documentation":"Raised as OSError by ZipProvider._extract_resource() when the module-level WRITE_SUPPORT flag is False. WRITE_SUPPORT is set by attempting `from os import mkdir, rename, unlink` at import time; on platforms where those are unavailable (historically Google App Engine and similar sandboxes) it falls to False, so resource extraction — which needs rename/unlink to atomically place extracted files — is impossible.","triggerScenarios":"Triggering resource extraction (via resource_filename on a zip/egg-backed module) on a platform where os.mkdir/os.rename/os.unlink could not be imported at pkg_resources import time, i.e. WRITE_SUPPORT is False.","commonSituations":"Deploying on Google App Engine (Python 2 sandbox origins), a heavily restricted container, or a read-only/filesystem-less runtime where the os write primitives are absent. Extraction is attempted and immediately refused.","solutions":["Avoid extraction: read resources as bytes via resource_string()/resource_stream(), which do not require rename/unlink.","Run in an environment with full os write support (a normal filesystem) so WRITE_SUPPORT is True.","If only a read-only filesystem is the issue, pre-extract resources to a writable temp dir out-of-band and reference them directly."],"exampleFix":"// before\npath = pkg_resources.resource_filename('pkg', 'data.bin')  # OSError on GAE\n\n// after\ndata = pkg_resources.resource_string('pkg', 'data.bin')  # no write needed","handlingStrategy":"validation","validationCode":"import pkg_resources\n\ndef can_extract():\n    return getattr(pkg_resources, 'WRITE_SUPPORT', False)\n\ndef safe_resource_filename_or_bytes(module, name):\n    if not can_extract():\n        return ('bytes', pkg_resources.resource_string(module, name))\n    return ('path', pkg_resources.resource_filename(module, name))","typeGuard":"import pkg_resources\n\ndef extraction_supported() -> bool:\n    return bool(getattr(pkg_resources, 'WRITE_SUPPORT', False))","tryCatchPattern":"try:\n    path = pkg_resources.resource_filename(pkg, name)\nexcept OSError as e:\n    if 'not supported on this platform' in str(e):\n        data = pkg_resources.resource_string(pkg, name)\n    else:\n        raise","preventionTips":["Read resources as bytes (resource_string) on platforms without os.rename/unlink.","Check pkg_resources.WRITE_SUPPORT before requesting extraction.","Run on a full filesystem when extraction is required."],"tags":["pkg-resources","platform","sandbox","extraction","gae"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}