pypa/pip · error · ImportError
{exc}
Error message
{exc} What it means
Raised as ImportError in EntryPoint.resolve() when functools.reduce(getattr, self.attrs, module) fails with AttributeError. The EntryPoint successfully imports the module but one of the dotted attribute lookups (e.g. 'cli.main') fails because the attribute doesn't exist on the object. The original AttributeError message is wrapped into an ImportError at line 2755.
Source
Thrown at src/pip/_vendor/pkg_resources/__init__.py:2755
".require separately.",
PkgResourcesDeprecationWarning,
stacklevel=2,
)
if require:
# We could pass `env` and `installer` directly,
# but keeping `*args` and `**kwargs` for backwards compatibility
self.require(*args, **kwargs) # type: ignore
return self.resolve()
def resolve(self) -> _ResolvedEntryPoint:
"""
Resolve the entry point from its module and attrs.
"""
module = __import__(self.module_name, fromlist=['__name__'], level=0)
try:
return functools.reduce(getattr, self.attrs, module)
except AttributeError as exc:
raise ImportError(str(exc)) from exc
def require(
self,
env: Environment | None = None,
installer: _InstallerType | None = None,
):
if not self.dist:
error_cls = UnknownExtra if self.extras else AttributeError
raise error_cls("Can't require() without a distribution", self)
# Get the requirements for this entry point with all its extras and
# then resolve them. We have to pass `extras` along when resolving so
# that the working set knows what extras we want. Otherwise, for
# dist-info distributions, the working set will assume that the
# requirements for that extra are purely optional and skip over them.
reqs = self.dist.requires(self.extras)
items = working_set.resolve(reqs, env, installer, extras=self.extras)
list(map(working_set.add, items))View on GitHub (pinned to f399c37189)
Solutions
- Verify the attribute exists in the target module by importing it manually first: `from mypkg import SomeClass`.
- Update the entry_points/entry point string in setup.cfg, pyproject.toml, or the .egg-info/entry_points.txt to reference the correct attribute path.
- Reinstall the package after fixing metadata so the entry_points.txt is regenerated.
- Check for typos in the attribute name or intermediate dotted path.
Example fix
// before: setup.cfg has // [console_scripts] // mycli = mypkg:main_old // but main_old was renamed to main // after // [console_scripts] // mycli = mypkg:main
Defensive patterns
Strategy: try-catch
Validate before calling
def entry_point_resolvable(ep) -> bool:
try:
module = __import__(ep.module_name, fromlist=['__name__'], level=0)
obj = module
for attr in ep.attrs:
obj = getattr(obj, attr)
return True
except (ImportError, AttributeError):
return False Type guard
def has_attribute_path(module_name: str, attrs: tuple) -> bool:
try:
import importlib
obj = importlib.import_module(module_name)
for a in attrs:
obj = getattr(obj, a)
return True
except (ImportError, AttributeError):
return False
Try / catch
try:
func = ep.load()
except ImportError as e:
# attribute not found; log and skip or use fallback
print(f'Entry point {ep} unresolved: {e}')
func = default_func
Prevention
- Keep entry_points.txt in sync with code after refactoring.
- Test entry point loading in CI after package install.
- Use try/except ImportError around ep.load() for plugin systems with optional plugins.
When it happens
Trigger: Calling entry_point.load() or entry_point.resolve() where the module imports fine but the specified attribute path (e.g. 'ClassName' or 'module.function') does not exist on the module or intermediate objects. For example, entry point 'foo = mypkg:NonExistentClass'.
Common situations: Refactoring that renames or removes a referenced function/class without updating entry_points metadata; wrong attribute specified in setup.cfg/pyproject.toml [project.scripts]; version mismatch where the installed package lacks the expected callable.
Related errors
- Entry point %r not found
- Error parsing entry points for {self.raw_name}: {e}
- Not a package:
- Invalid module name
- EntryPoint must be in 'name=module:attrs [extras]' format
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/d50909a1b41b0632.
Report an issue: GitHub.