Deconflict Overlapping Error Type Usage
Checklist
- I added a descriptive title
- I searched open requests and couldn't find a duplicate
What is the idea?
While documenting Group A errors for #16663 (epic #16274), the exception taxonomy turned out to carry more types than there are actual user situations. Four exception names currently cover three stories, and one of them prints the wrong story depending on a constructor argument and also covers two different situations.
There should be one-- and preferably only one --obvious way to do it.
This issue is for agreeing on a target shape to reduce options and disambiguate situations of when to use which error.
Current shape
| Type | Raised from | User situation |
|---|---|---|
PackageNotInstalledError |
update, list --full-name |
Not in this environment |
PackagesNotFoundInPrefixError |
remove (+ conversions) |
Not in this environment |
PackagesNotFoundError (base) |
search --envs |
Not in any environment |
PackagesNotFoundError (libmamba) |
libmamba install (when channels is supplied) | Not in configured channels |
PackagesNotFoundError (libmamba) |
libmamba remove path (when no channel is supplied) | Not in environment |
PackagesNotFoundInChannelsError |
create/install/update/search/clone/--revision |
Not in configured channels |
The overlaps
1. PackagesNotFoundInPrefixError is a documented alias of PackageNotInstalledError.
Same meaning, same message branch — the child, PackagesNotFoundInPrefixError, just assumes an iterable so the multi-package text is used. PackageNotInstalledError also handles this case. Interesting enough PackageNotInstalledError inherits from PackagesNotFoundError which seems weird to go from plural to singular.
2. The identity of base type, PackagesNotFoundError, depends on channel_urls.
PackagesNotFoundError renders "not available from current channels" when channel_urls is set and "missing from the target environment" when it isn't. So PackagesNotFoundInChannelsError constructed with an empty channel list prints a prefix-miss message under a channel-miss type name. So the use can be used to either fill the Packages not in environment (or environments see next point) and if a package isn't found in the current channel configuration. It is used both ways in conda-libmamba-solver and also has code in conda to recast it to PackagesNotFoundInChannelsError if it has been raised during transaction handling. Also even in its own documentation it states:
"""Base error for missing packages.
Prefer raising one of the more specific subclasses:
- :class:`PackagesNotFoundInChannelsError` – packages unavailable in channels.
- :class:`PackageNotInstalledError` – packages missing from a target prefix.
"""3. search --envs uses PackagesNotFoundError type no channels mode for a local-env miss.
main_search.py:213 raises the PackagesNotFoundError with no channels, so it inherits the prefix wording, "The following packages are missing from the target environment: <package list". It should be more along the lines of "Not found in any local environment" as a third distinct situation.
Why is this needed?
There shouldn't be Errors that can serve two purposes and having specialized cases for iterables is too special. Errors should be able to handle one or multiple cases as is already done.
What should happen?
Proposal
Collapse to three types, one per user situation:
| Situation | Type |
|---|---|
| Not in this environment | Package(s)NotInstalledError |
| Not in any local environment | new/renamed type for search --envs |
| Not in the configured channels | PackagesNotFoundInChannelsError |
Strategy:
- Fix known callers of
PackagesNotFoundError(i.e. inconda-libmamba-solver) and pass the appropriate error case. - Move
PackagesNotFoundErrorto a pure base class that does not broadcast any message and protects against doing so.
- It's only job is to hold packages.
PackagesNotFoundInChannelsErrorowns channels casePackageNotInstalledErrorandPackagesNotFoundInPrefixErrorreplacement will own local case
- Deprecate
PackageNotInstalledErrorandPackagesNotFoundInPrefixErrorwhile creating thePackagesNotInstalledErrorin the style ofPackagesNotFoundInPrefixErrorthat accepts prefix for proper identification of environment.PackagesNotInstalledErrorshould handle singular and multiple cases. - Create new type of error that handles the Packages not found in any local environment case. It's one job is to be raised in the search --envs case. It is the local equivalent of
NotFoundInChannels.
Dependency order:
- Immediately
- The new errors could be created immediately (part of 3 and 4)
- Fixes to base class being called in conda-libmamba-solver and others (1)
- Longer term
- Move of
PackagesNotFoundErroras non callable base class (2)- Need to deprecate notice the using channels as part of the
PackagesNotFoundErrorinstance creation.
- Need to deprecate notice the using channels as part of the
- Start deprecation notices for
PackageNotInstalledErrorandPackagesNotFoundInPrefixError. (3)
- Move of
Additional Context
No response
Source: conda/conda