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
- 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.
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
- 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.
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
- "os.mkdir" not supported on this platform.
- Can't change extraction path, files already extracted
- resource_filename() only supported for .egg, not .zip
- "egg_name" is empty. This likely means no egg could be found
- {wheel.filename} is not a supported wheel for this platform.
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/bc534d593f74a2e4.json.
Report an issue: GitHub.