pypa/pip · error · OSError
"egg_name" is empty. This likely means no egg could be…
Error message
"egg_name" is empty. This likely means no egg could be found from the "module_path".
What it means
Raised by ZipProvider._extract_resource when self.egg_name is empty/falsy. The egg_name is set during _setup_prefix by walking parent paths looking for a directory matching the .egg naming convention; if none is found, egg_name stays empty. This means the zip-backed resource provider cannot construct a cache path for extraction. Extraction from a bare .zip (not an .egg) is fundamentally unsupported.
Solutions
- Package the resource inside a properly named .egg or wheel (.whl) archive so the egg_name can be derived from the path.
- Use an alternative resource access API (e.g. resource_string / resource_stream) that does not require extraction to the filesystem.
- Ensure the archive filename matches the convention ProjectName-version-pyX.Y.egg so _is_egg_path returns True during _setup_prefix.
- If you control the packaging, switch to wheel format which pkg_resources recognizes via its dist-info/egg-info metadata.
Example fix
// before (resource lives in plain data.zip on sys.path)
from pkg_resources import resource_filename
path = resource_filename('mypkg', 'data.csv') # raises OSError
// after (repackage as wheel/egg, or read from stream)
from pkg_resources import resource_string
data = resource_string('mypkg', 'data.csv') Defensive patterns
Strategy: validation
Validate before calling
from pkg_resources import ZipProvider
provider = resource_manager(provider_of_module)
if isinstance(provider, ZipProvider) and not getattr(provider, 'egg_name', ''):
# cannot extract; use stream access instead
data = resource_string('mypkg', 'data.csv')
else:
path = resource_filename('mypkg', 'data.csv') Type guard
import re
def is_valid_egg_path(path: str) -> bool:
return bool(re.match(r'^[\w.]+-\d[^-]+-py\d', os.path.basename(path)))
Try / catch
from pkg_resources import resource_filename
try:
path = resource_filename('mypkg', 'data.csv')
except OSError:
# fallback: read as string
data = resource_string('mypkg', 'data.csv')
Prevention
- Package resources in .whl or .egg archives, not plain .zip files.
- Prefer resource_string/resource_stream over resource_filename when extraction isn't strictly needed.
- Test resource access in the deployment environment, not just locally.
When it happens
Trigger: Calling resource_filename() or get_resource_filename() on a resource that lives inside a plain .zip archive rather than an .egg/whl, or when the module_path does not have a recognizable egg ancestor directory. The check at line 2046 (`if not self.egg_name`) fires inside _extract_resource which is reached via get_resource_filename -> _extract_resource.
Common situations: Bundling dependencies as raw .zip files on sys.path instead of .egg or .whl; running on an import hook that registers a zip importer without egg-style naming; legacy packaging tools that produced non-egg zip archives; calling pkg_resources.resource_filename on a module loaded from a zip.
Related errors
- resource_filename() only supported for .egg, not .zip
- Can't change extraction path, files already extracted
- "os.rename" and "os.unlink" are not supported on this…
- Algorithm used in hash field has different value in hashes…
- Algorithm used in hash field is not present in hashes field
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/4bd148c9ea514c03.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_vendor/pkg_resources/__init__.py:2047
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)
utime(tmpnam, (timestamp, timestamp))
manager.postprocess(tmpnam, real_path)
try:
rename(tmpnam, real_path)View on GitHub (pinned to f399c37189)