pypa/pip · error · NotImplementedError
resource_filename() only supported for .egg, not .zip
Error message
resource_filename() only supported for .egg, not .zip
What it means
Raised by ZipProvider.get_resource_filename() when self.egg_name is empty/falsy. ZipProvider extracts zip-archived resources to a cache directory keyed by the egg name; without an egg name there is no stable extraction directory, so it refuses. This indicates the resource lives in a plain .zip rather than a named .egg, which this code path does not support for filesystem extraction.
Solutions
- Use resource_stream()/resource_string() instead of resource_filename() to read zip contents without extraction.
- Package the code as an .egg (with EGG-INFO) so egg_name is populated.
- Install the package normally on the filesystem rather than running from a bare .zip.
Example fix
// before
# module loaded from plain .zip, no egg_name -> NotImplementedError
path = resource_filename('mypkg', 'data.txt')
// after
# read bytes directly without extraction
data = resource_string('mypkg', 'data.txt') Defensive patterns
Strategy: fallback
Validate before calling
# Check if provider is a ZipProvider without egg_name before calling resource_filename
from pkg_resources import ZipProvider
if isinstance(provider, ZipProvider) and not provider.egg_name:
# use stream-based access instead
data = resource_string('pkg', name) Try / catch
try:
path = resource_filename('pkg', name)
except NotImplementedError:
data = resource_string('pkg', name) # fallback: read bytes Prevention
- Prefer resource_stream()/resource_string() for zipped packages.
- Package as .egg or install on filesystem if you need real paths.
When it happens
Trigger: Calling resource_filename() (which routes to get_resource_filename) for a package imported from a .zip archive that is not an .egg and has no egg name set, so self.egg_name is ''.
Common situations: Packaging code in a plain .zip and adding it to sys.path; an import hook that serves modules from a zip without egg metadata; legacy zipped modules without EGG-INFO.
Related errors
- "egg_name" is empty. This likely means no egg could be…
- Can't change extraction path, files already extracted
- "os.rename" and "os.unlink" are not supported on this…
- `base` parameter in `_fn` is `None`. Either override this…
- Can't perform this operation for loaders without…
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/2c08b72b318a4b01.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_vendor/pkg_resources/__init__.py:2011
if fspath.startswith(self.zip_pre):
return fspath[len(self.zip_pre) :]
raise AssertionError("%s is not a subpath of %s" % (fspath, self.zip_pre))
def _parts(self, zip_path):
# Convert a zipfile subpath into an egg-relative path part list.
# pseudo-fs path
fspath = self.zip_pre + zip_path
if fspath.startswith(self.egg_root + os.sep):
return fspath[len(self.egg_root) + 1 :].split(os.sep)
raise AssertionError("%s is not a subpath of %s" % (fspath, self.egg_root))
@property
def zipinfo(self):
return self._zip_manifests.load(self.loader.archive)
def get_resource_filename(self, manager: ResourceManager, resource_name: str):
if not self.egg_name:
raise NotImplementedError(
"resource_filename() only supported for .egg, not .zip"
)
# no need to lock for extraction, since we use temp names
zip_path = self._resource_to_zip(resource_name)
eagers = self._get_eager_resources()
if '/'.join(self._parts(zip_path)) in eagers:
for name in eagers:
self._extract_resource(manager, self._eager_to_zip(name))
return self._extract_resource(manager, zip_path)
@staticmethod
def _get_date_and_size(zip_stat):
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, sizeView on GitHub (pinned to f399c37189)