pypa/pip · error · OSError

"os.rename" and "os.unlink" are not supported on this platfo

Error message

"os.rename" and "os.unlink" are not supported on this platform

What it means

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.

Source

Thrown at src/pip/_vendor/pkg_resources/__init__.py:2042

        size = zip_stat.file_size
        # ymdhms+wday, yday, dst
        date_time = zip_stat.date_time + (0, 0, -1)
        # 1980 offset already done
        timestamp = time.mktime(date_time)
        return timestamp, size

    # FIXME: 'ZipProvider._extract_resource' is too complex (12)
    def _extract_resource(self, manager: ResourceManager, zip_path) -> str:  # noqa: C901
        if zip_path in self._index():
            for name in self._index()[zip_path]:
                last = self._extract_resource(manager, os.path.join(zip_path, name))
            # return the extracted directory name
            return os.path.dirname(last)

        timestamp, size = self._get_date_and_size(self.zipinfo[zip_path])

        if not WRITE_SUPPORT:
            raise OSError(
                '"os.rename" and "os.unlink" are not supported on this platform'
            )
        try:
            if not self.egg_name:
                raise OSError(
                    '"egg_name" is empty. This likely means no egg could be found from the "module_path".'
                )
            real_path = manager.get_cache_path(self.egg_name, self._parts(zip_path))

            if self._is_current(real_path, zip_path):
                return real_path

            outf, tmpnam = _mkstemp(
                ".$extract",
                dir=os.path.dirname(real_path),
            )
            os.write(outf, self.loader.get_data(zip_path))
            os.close(outf)

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Avoid extraction: read resources as bytes via resource_string()/resource_stream(), which do not require rename/unlink.
  2. Run in an environment with full os write support (a normal filesystem) so WRITE_SUPPORT is True.
  3. If only a read-only filesystem is the issue, pre-extract resources to a writable temp dir out-of-band and reference them directly.

Example fix

// before
path = pkg_resources.resource_filename('pkg', 'data.bin')  # OSError on GAE

// after
data = pkg_resources.resource_string('pkg', 'data.bin')  # no write needed
Defensive patterns

Strategy: validation

Validate before calling

import pkg_resources

def can_extract():
    return getattr(pkg_resources, 'WRITE_SUPPORT', False)

def safe_resource_filename_or_bytes(module, name):
    if not can_extract():
        return ('bytes', pkg_resources.resource_string(module, name))
    return ('path', pkg_resources.resource_filename(module, name))

Type guard

import pkg_resources

def extraction_supported() -> bool:
    return bool(getattr(pkg_resources, 'WRITE_SUPPORT', False))

Try / catch

try:
    path = pkg_resources.resource_filename(pkg, name)
except OSError as e:
    if 'not supported on this platform' in str(e):
        data = pkg_resources.resource_string(pkg, name)
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04). Data as JSON: /data/errors/bc534d593f74a2e4.json. Report an issue: GitHub.